CSLA .NET

Vibrant discussion about CSLA .NET and using the framework to build great business applications.

Can I treat CSLA BusinessBase class as EF4 Code First classes

rated by 0 users
Answered (Verified) This post has 1 verified answer | 7 Replies | 3 Followers

Top 500 Contributor
30 Posts
Tiklu Ganguly posted on Wed, Sep 29 2010 2:24 AM

Hi,

     Based on my understanding it is quite possible to treat the csla buisnessbase (or readonlybusinessbase) classes as ef4 code first classes.

          Please do let me know if I am correct.

 

Regards

Tiklu

Answered (Verified) Verified Answer

Top 10 Contributor
9,270 Posts

If you are able to get this to work, please share your findings.

I suspect it might work in some simple cases, but probably won't work if the object graph is anything but trivial, and I can't imagine it would work if you use managed backing fields (which are basically required to support Silverlight or WP7).

Remember that any code external to your object (such as an ORM) can't get/set property values directly, because that'll trigger business rules. The best case is that performance would be poor, but more likely the object will refuse to get/set some values due to authorization rules.

So any external code really needs to set field values, not property values. Technologies like BinaryFormatter and NetDataContractSerializer do this, which is why they work well for CSLA. Perhaps EF can do this too?

But if you use managed backing fields, then you have no private fields, in which case any external code actually needs to invoke ReadProperty/LoadProperty - and that implies that the external technology (like EF) has hooks where you can plug in your own code for any get/set operations.

At one point the EF team did plan to have such hooks in EF 4, and I'd discussed with them how this might work. I don't think that feature made it into the final release of EF though. But if I'm wrong, I'd love to hear about it - because it would be really cool :)

Rocky

All Replies

Top 10 Contributor
9,270 Posts

If you are able to get this to work, please share your findings.

I suspect it might work in some simple cases, but probably won't work if the object graph is anything but trivial, and I can't imagine it would work if you use managed backing fields (which are basically required to support Silverlight or WP7).

Remember that any code external to your object (such as an ORM) can't get/set property values directly, because that'll trigger business rules. The best case is that performance would be poor, but more likely the object will refuse to get/set some values due to authorization rules.

So any external code really needs to set field values, not property values. Technologies like BinaryFormatter and NetDataContractSerializer do this, which is why they work well for CSLA. Perhaps EF can do this too?

But if you use managed backing fields, then you have no private fields, in which case any external code actually needs to invoke ReadProperty/LoadProperty - and that implies that the external technology (like EF) has hooks where you can plug in your own code for any get/set operations.

At one point the EF team did plan to have such hooks in EF 4, and I'd discussed with them how this might work. I don't think that feature made it into the final release of EF though. But if I'm wrong, I'd love to hear about it - because it would be really cool :)

Rocky

Top 500 Contributor
30 Posts

Hi Rocky,

          First of all sorry for replying you back after so many days. Please do have a look at my code which I have attached to this post. As you can see it is basically a very simple object getting saved to the db. To run the code you would be needing ef4 futures ctp 4 and obviously CSLA 4. If you see the dbcontext class you will see that I have specifically mapped only the properties which I need to put in the db, which is actually skipping all the other businessbase classes like isbusy, isdirty etc. 

           Also if you see the code is written in a very simple way. If required we can even improve the performance of saving/loading data with the help of doing some server side caching of the dbcontext. Also I do believe by following this technique we can also save very complex data's too. I am still doing some research of my own to extend this demo to work on some more complex data graph.

        Please do let me know your feedbacks on it

Regards

Tiklu

 

Top 10 Contributor
9,270 Posts

I'll try to look at this when I get a chance, but it won't be any time soon.

The one thing to remember is that you can't use property getters and setters directly without running authorization and business rules. To avoid that you need to call ReadProperty and LoadProperty, which aren't normally public. However, if you can put the EF related code into an ObjectFactory subclass you can get at those methods.

Rocky

Top 500 Contributor
30 Posts

Got It, I will go in that direction. Also you are correct if we directly use setproperty and getproperty, which is what i have used in my code it would prevent an user from loading a particular value from db if he does not have a permission, and which in turn may just crash the whole code. 

            Lets see if i can come up with something with ObjectFactory. I will surely post you my findings on that

Top 500 Contributor
30 Posts

Hi Rocky,

            As you said the trick was to somehow skip the setpropery and getpropery methods, and this is how I did it.

 

First I created one EFBusinessBase which inherits from BusinessBase and overriden the setproperty like this

 

 

public new void SetProperty<P>(PropertyInfo<P> propertyInfo, P newValue)

        {

            if (isReady)

            {

                base.SetProperty<P>(propertyInfo, newValue);

            }

            else

            {

                base.LoadProperty<P>(propertyInfo, newValue);

            }

        }

 

 

Similarly for get property it is

 

 

public new P GetProperty<P>(PropertyInfo<P> propertyInfo)

        {

            if (isReady)

            {

                return base.GetProperty<P>(propertyInfo);

            }

            else

            {

                return base.ReadProperty<P>(propertyInfo);

            }

        }

 

 

I also have another method in the business base called MarkReady as

 

 

void IEFBusinessBase.MarkReady()

        {            

            this.isReady = true;

        }

 

Now I did also created a new class called CSLADBContext where in ObjectMaterialized event I am doing the following

 

void ObjectContext_ObjectMaterialized(object sender, System.Data.Objects.ObjectMaterializedEventArgs e)

        {

            var entity = e.Entity as IEFBusinessBase;

            if (entity != null)

            {

                entity.MarkReady();

            }

        }

 

So this event actually gets fired once all the values for an entity is set and at that time i am also setting the the isready flag variable to true. and thus enabling the business validations and authorization rules only after the object is fully materialized. 

Also inside the dataportal_fetch I am just directly adding the objects to the list like this

protected void DataPortal_Fetch()

        {

            PersonDbContext ctx = new PersonDbContext();

            ctx.Database.CreateIfNotExists();

            var items = from p in ctx.Persons select p;

            this.RaiseListChangedEvents = false;

            foreach (var itm in items)

            {

                Add(itm);

            }

 

            this.RaiseListChangedEvents = true;

        }

As you can see i am directly adding the items to the list. The only problem that I am getting with this is the person objects are not properly responding to the property change (i.e not marking an object as dirty)...I think I do have to add some code for that in the MarkReady method. If you can give me some hint here, then that would be nice...

  Again I have added the code with this reply...in case you find this post interesting then please do have a look at that

 

Regards

Tiklu

Top 500 Contributor
30 Posts

Hi Rocky,

             The last problem that I was getting because I was not serializing isReady using the mobile formtter. Now I did that and it is working fine now..

As of now the MarkReady has been changed like this

 

void IEFBusinessBase.MarkReady()

        {

            this.MarkAsChild();

            this.MarkOld();            

            this._isReady = true;

        }

 

and I have added the _isReady variable to mobileformatter as

 

protected override void OnSetState(Csla.Serialization.Mobile.SerializationInfo info, Csla.Core.StateMode mode)

        {

            base.OnSetState(info, mode);

            _isReady = info.GetValue<bool>("Mazik.EFCSLA._isReady");

        }

 

        protected override void OnGetState(Csla.Serialization.Mobile.SerializationInfo info, Csla.Core.StateMode mode)

        {

            base.OnGetState(info, mode);

            info.AddValue("Mazik.EFCSLA._isReady", this._isReady);

        }

Now it is working fine

Regards

Tiklu

 

Top 10 Contributor
9,270 Posts

That's great!

Rocky

Page 1 of 1 (8 items) | RSS

Copyright (c) 2006-2010 Marimer LLC. All rights reserved.
Email admin@lhotka.net for support.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems