A problem I get when adding BL code to entity classes

Posts   
 
    
Ian avatar
Ian
User
Posts: 511
Joined: 01-Apr-2005
# Posted on: 20-Nov-2009 17:15:40   

Hi there,

Lets say I have a generated entity class which is mapped to a table and I add BL code to the class that operates on the data from an instance of that class. Often what happens is that I'll bring similar data into my app via a view but of course the view doesn't have the code on it to operate on the similar data unless I duplicate the code. Which of course I don't want to do!

So for example here is an entity class that I've add some business logic to - its a method called 'IsBig' which operates on a generated property which maps to a field in a db table.


    public partial class MyEntity
    {
        public bool IsBig
        {
            get { return MyProperty > 5; }
        }
    }

Now lets suppose I create a view which happens to select the MyProperty field from the MyEntity table. This view is mapped to another new entity class called 'VwMyEntity'. The question is, how do I go about calling 'IsBig' on VwMyEntity without duplicating the code?

I can see a few options:

  1. Don't use views and only ever have one property in one's solution which maps to a db field.
  2. Link VwMyEntity to MyEntity in LLBLGen designer and prefetch a MyEntity instance for every VwMyEntity returned and defer all BL logic to the MyEntity instance.
  3. Factor out an interface and have both MyEntity and VwMyEntity implement it and have them both delegate their implementation to a third class that one passes the instance data to to be operated upon.

So the above example would look something like this:


        public interface IMyEntity
        {
            bool IsBig { get; }
        }

        public class IMyEntityImp
        {
            public bool IsBig(int i)
            {
                return i > 5;
            }
        }

        public partial class MyEntity : IMyEntity
        {
            public bool IsBig
            {
                get
                {
                    var obj = new IMyEntityImp();
                    return obj.IsBig(MyProperty);
                }
            }
        }

        public partial class VwMyEntity : IMyEntity
        {
            public bool IsBig
            {
                get
                {
                    var obj = new IMyEntityImp();
                    return obj.IsBig(MyProperty);
                }
            }
        }

None of these seem very satisfying. Any ideas? Surely I'm not the only one that's come up against this. simple_smile

Ian.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 20-Nov-2009 20:33:42   

Ian,

In my opinion you could:

A. Inherit from the actual generated entity. (MyEntityA : MyEntity, and MyEntityB : MyEntity)

or

B. You could make two entities on LLBLGen Designer (MyEntity and VwMyEntity) and specify additional interfaces on LLBLGen Designer.

David Elizondo | LLBLGen Support Team
rdhatch
User
Posts: 198
Joined: 03-Nov-2007
# Posted on: 20-Nov-2009 21:15:21   

Jeremiah & I are in the process of solving these very problems as we speak.

Like you, I used to write all my calculations in get{} properties on my Entities. Not anymore.

You can write your Lambda calculation against an interface for your Entity, such as you have: IMyEntity. Take this in, return a boolean. Like so:


        Expression<Func<IMyEntity, bool>> calc_IsBig()
        {
            return (entity) => (entity.MyProperty > 5);
        }

Using an Obtics ValueProvider on this Lambda against your IMyEntity interface - You can use one business calculation for both your Entities and your View.

Hope this helps!

Ryan

Ian avatar
Ian
User
Posts: 511
Joined: 01-Apr-2005
# Posted on: 01-Dec-2009 05:05:48   

rdhatch I haven't looked too closely at Obtics yet but

centralize all your business logic for calculations

sounds like your idea is to take member functions and turn them into non-member functions which are passed an instance of an interface.

How does this handle polymorphism? i.e. how does one vary the code that gets called based on the concrete runtime type of the interface?

Also do you think that maybe we are running into a problem with OO programming? i.e. that methods become member functions on one class when its often useful to use the same code on a variety of similar data types?