Updating data using Entity Framework in N-Tier and N-Layer Applications (short lived EF contexts) – (Part 1)


First of all, we are talking about using Entity Framework and how it fits within N-Tier and N-Layer applications, ok?, that’s our initial scenario.


An N-Tier application is an application where you have 3 or more physical tiers. I mean with that things like, “Presentation/Client Tier”, “Application/Business Server Tier” and “Data Tier” (a database server in most of the cases) and nowadays we use web services (or even better, WCF Services) to communicate between presentation tier and the application server tier. Here you see a simple & typical picture about N-Tier architecture:


clip_image002


As you can see, all the client applications (we could be for instance WinForms, WPF, or even Silverlight apps) need to remotely access to the application Server tier using for example WCF Services.


Also, in my opinion. RIA (Rich Internet Applications) is a special subset of N-Tier apps.


A different matter is that we’d probably design our application as an N-Layer application, I mean, with several logic layers where we implement different logic tasks. For example we could have the DAL layer (Data Access Layer), BLL Layer (Business Logic Layer), BFLL Layer (Busines Façade Logic Layer), WCF Service Layer and several Presentation layers depending of the pattern we use, like MVC (Model-View-Controller), MVP (Model-View-Presenter), etc.. Also, within the N-Layer architecture, you can guess that Entity Framework fits as the DAL Layer (Data Access Classes) as well as using EF entities as our disconnected entities to pass thru all the layers, all right?


image


BTW, not all N-Layer apps should be N-Tier apps, but all N-Tier Apps must internally be designed as N-Layer. I mean, there are many cases where the less you physically split your model, the better for performance (more tiers is good for scalability but not for pure performance, due to latencies). Remember, N-Layer is about logic layers.


OK!, so if we get back to the N-Tier architecture (physical tiers), like I said, we need remote mechanisms to communicate the client tier with the application server tier (for instance, WCF Services) and therefore when we query the database from the app server tier, to obtain data (like an Order), we keep it as an EF entity, then we disconnect it from the EF context (detach), WCF serializes it and sends that disconnected entity to the presentation tier (client apps & machines).


So, most enterprise applications use an architectural pattern that needs a stateless facade for its business logic (like N-Tier & N-Layer apps). They have scenarios like WebServices or WCF, ASP.NET applications, Traditional Desktop Application (Windows Forms, WPF) consuming WCF Services, etc. in those cases data access works “disconnected oriented”, I mean, database data (in the real tables) are not blocked while the user is working in the client tier (btw, this is better for scalability). So, in the client/presentation tier, the user will be working and maybe, he changes that entity’s data (which is disconnected from the server) and after a while (at any time) the user submits that data to the application server and then the DAL layer (Entity Framework and LINQ to EF, in our case) will update that data into the database. Right?. Well, if we just do that, it will be just a “Last-In-Wins” or what I call, a “Too Optimistic Update” 😉 . Well, in many apps which are not very exigent or complex regarding updates, this can be enough, but then, we could have other apps where the users need to know if data (regarding the same entity and records he is using at client tier) has changed in the database while he was working and before he tried to update the data. In that case we should use “Optimistic Concurrency Updates” managing “Optimistic Concurrency Exceptions”.


So, I am using all the following stuff:


Entity Framework and LINQ to Entities as our DAL Layer


WCF as our remote communication technology


– Any .NET UI technology as our client App (WPF, WinForms, OBA or even Silverlight)


Simple way: Updating data in N-Tier applications and using Entity Framework with detached entities


In order to understand what I mean, first of all, I am going to explain how to implement just simple updates in N-Tier applications and using Entity Framework. So this case is the one I called “Last-In-Wins” or a “Too Optimistic Update” ;-). So in this first case I won’t manage any Optimistic Concurrency Exception.


First of all, we’d have a business class (BLL class) which would be using EF & LINQ to Entities so that class would be querying the database; let’s say to get a Customer data and to return that entity’s data to the client/presentation tier (thru a WCF Service). The BLL class code could be something like the following code:






public class CustomerBll


{


    private MyDataBaseEntities context;


    public CustomerBll()


    {


        context = new MyDataBaseEntities();


    }


    public Customer GetCustomer(string customerID)


    {


        var q = from c in context.Customers //.Include(“Orders”)


        where c.CustomerID == numCustomerID


        select c;


        var customer = q.First();


        context.Detach(customer);


        return customer;


}


Ok, if you know LINQ to entities, this is a very simple method, right?. The important thing to take into account is the following: “we are returning a disconnected/detached entity data object” passing it to the upper layers (Service layeràPresentation Layers). It means that regarding Entity Framework we’ll be working with ObjectContext objects in a “short lived context” way. Basically, when we’ll close the loop, we’ll need to re-attach modified EntityObjects, that were updated outside of an ObjectContext (in detached state). This is a very common scenario when we’re using stateless facades (most N-Tier & N-Layer apps).


Coming back to our code, then we could have a WCF Service serializing & returning the disconnected/detached entity.


Here you could see the Service contract for the method:






//WCF Contract


[OperationContract]


Customer CustomerBll_GetCustomer(string customerID);




//And now, the method’s implementation in the WCF class library:


public Customer CustomerBll_GetCustomer(string customerID)


{


    return new CustomerBll().GetCustomer(customerID);


}


Ok, after that, the client app would be consuming the WCF Service and will display the entity’s data (customer’s data) let’s say in a WPF form. Remember that right now, the client app is working with a disconnected/detached entity object and there is not an ObjectStateManager tracking changes. We’ll see how it affects later on…


So, once the data is visible within a form, the user can start changing some data in that form until he decides to actually update that data into the application (for me, it means he wants to update that data into the database), pressing, for instance a big button which says “Update”. J
Right, in this very moment the client application would be calling another WCF Service method called something like UpdateCustomer(), like you see down below:






public void CustomerBll_UpdateCustomer(Customer customer)


{


    new CustomerBll().UpdateCustomer(customer);


}


Then, that WCF method is calling the real business logic method, and this is where I am going to show you how to use Entity Framework to update the detached/disconnected but modified entity which is coming back from the client tier. This is the code (remember this is the simple case, I am not managing optimistic concurrency exceptions here):






public void UpdateCustomer(Customer customer)


{


    //(CDLTLL) Entity must first be reunited with a Context


    //Note I do it with my custom extensor method for disconected environments (N-Tier, etc.)


    context.AttachUpdated(customer); //Custom extensor method


    context.SaveChanges();


}


Ok, first, in order for the context to be able to update anything (the entity) into the database using SaveChanges(), it has first to have it attached to the context. So, context.SaveChanges() is an EF regular method we always gotta use to update data (changes). But if we’d just use the method context.Attach(customer) before that, it won’t work because that customer entity is new for the context (it was originally detached, serialized and sent to the client tier) and now the context does not know nothing about it, the context “thinks” it is a new entity object and it would not know any changes to update using the context.SaveChanges().


The following is wrong code:






public void UpdateCustomer(Customer customer) //WRONG CODE


{


    //(CDLTLL) Entity must first be reunited with a Context


    context.Attach (customer); //Custom extensor method


    context.SaveChanges();//In this case, nothing happens here…


}


So in this simpler case, when you’d call SaveChanges() nothing would happen.


That is why I created a custom EF extensor method called “context.AttachUpdated()”. To be able to attach updated entities which are disconnected and coming from the client Tier.


It is the following code:






public static void AttachUpdated(this ObjectContext context, EntityObject objectDetached)


{


    if (objectDetached.EntityState == EntityState.Detached)


    {


        object currentEntityInDb = null;


        if (context.TryGetObjectByKey(objectDetached.EntityKey, out currentEntityInDb))


        {


            context.ApplyPropertyChanges(objectDetached.EntityKey.EntitySetName, objectDetached);


            //(CDLTLL)Apply property changes to all referenced entities in context


            context.ApplyReferencePropertyChanges((IEntityWithRelationships)objectDetached,


                                                                                (IEntityWithRelationships)currentEntityInDb); //Custom extensor method


        }


        else


        {


             throw new ObjectNotFoundException();


        }


    }


}


So, first of all we need to know what is new in this entity, I mean, what are the changes compared with the data we actually have in the database. In order to do that we’d need to query the database and get the actual data using the “context.TryGetObjectByKey()” method and attach it as the original data for that entity within the context.


Then, we can call the “context.ApplyPropertyChanges()” providing our new updated entity. What EF does is that it compares the original data (actual data in the database) with our new/updated entity and then it updates within the context all the property changes just regarding our specific entity (Customer, in this case). After that, when we call to “context.SaveChanges()” in the main method, EF will detect what are actually those changes and it will be able to update it into the real database (SQL Server, for instance).


Notice that after calling to “context.ApplyPropertyChanges()” I am calling another method called “ApplyReferencePropertyChanges()”. This other method is actually another extensor method which applies all my entity property changes but into all the referenced entities within our EF model (Customer could be related to Company, Order, etc.). This is an important method, otherwise we’ll be taking into account just our isolated entity (Customer). Here you can see my “context.ApplyReferencePropertyChanges()” custom context extensor method:






public static void ApplyReferencePropertyChanges(this ObjectContext context,


IEntityWithRelationships newEntity,


IEntityWithRelationships oldEntity)


{


    foreach (var relatedEnd in oldEntity.RelationshipManager.GetAllRelatedEnds())


    {


        var oldRef = relatedEnd as EntityReference;


        if (oldRef != null)


        {


            // this related end is a reference not a collection


            var newRef = newEntity.RelationshipManager.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;


            oldRef.EntityKey = newRef.EntityKey;


        }


    } 


}


So with that, we’re done!, it works ok following the method I said “Last In Wins” or a “Too Optimistic Update” 😉


Btw, another option (it works almost the same) would be not to query the database to know the actual data (kind of original data for the context) with “context.TryGetObjectByKey()” but to say to the context that all the properties within my entity have actually changed, “just because I say it”. After that, when we call “context.SaveChanges()” it will update all the entity properties just because we said that!. J


Here you can see this other entity extensor method (In this case I coded as an entity extensor method instead as a context extensor method, ok?):






public static void SetAllModified<T>(this T entity, ObjectContext context) where T : IEntityWithKey


{


    var stateEntry = context.ObjectStateManager.GetObjectStateEntry(entity.EntityKey);


    var propertyNameList = stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(pn => pn.FieldType.Name);


    foreach (var propName in propertyNameList)


    {


        stateEntry.SetModifiedProperty(propName);


    }


}


In this other case (using SetAllModified()) our code within “UpdateCustomer()” would be somethin like:






public void UpdateCustomer(Customer customer)
{
    context.Attach(customer);
    customer.SetAllModified(context);     // custom extension method
    context.SaveChanges();
}


Cool!, this seems all great, we are happy and we are living in a wonderful world. Sure?. Well, it depends, but like I said at the beginning of this post, this code we have written does not cover scenarios where we want to manage “Optimistic Concurrency Updates & Exceptions”, I mean, let’s say any other guy changed some data, regarding that same data customer, during the timeframe after I performed my Customer query but before I actually updated it to the database. I mean, someone changed data in the database just before I called to context.AttachUpdated(customer) and context.SaveChanges(). Ok, then, the initial original user won’t be aware that he might be over writing that new data that the other second user updated… In many cases this can be dangerous depending on the application’s type.


Well, I guess this post is getting too long, I’ll write a second post (very soon) explaining “How to: Update data in N-Tier applications and using Entity Framework with detached entities and managing Optimistic Concurrency Updates and Exceptions”.


— My second part of this post-article is here:


Optimistic Concurrency Updates using Entity Framework in N-Tier and N-Layer Applications (Part 2)


http://blogs.msdn.com/cesardelatorre/archive/2008/09/05/optimistic-concurrency-updates-using-entity-framework-in-n-tier-and-n-layer-applications-part-2.aspx

Comments (15)

  1. roahnluo says:

    great article!! works perfectly on my machine!

  2. Alex says:

    Just a little note. In GetCustomer method

    q.First();

    will throw an exception if there is no such ID.

    Should be checked for number of records returned.

    var q = from c in context.Customers //.Include("Orders")

           where c.CustomerID == numCustomerID

           select c;

    if (q.Count()==0) //return null or whatever;

  3. wojtek says:

    thank You for this great article!

    regards

  4. dmorgan says:

    Hi, I now this is kind of old, but I got a question: does the SetAllModified method work updating entities referenced in the object to update?

  5. Better N-Tier Concurrency Management for the Entity Framework Posted in Technical at 11:03 am by Tony

  6. BillGan says:

    从Oxite看使用了ADO.NETEntityFramework的应用程序的多层架构 之前经常看到有人问使用了ADO.NETEntityFramework或LinqtoSQL的项…

  7. Snowdream says:

    本文介绍了在使用 ADO.NET Entity Framework 或 Linq to SQL 的项目中进行多(三)层架构设计的思路,这些思路来源于学习Oxite得到的启发。

  8. Sonny Man says:

    Entity Framework in N-Tier and N-Layer Applications

  9. AugustoRuiz says:

    Hi César,

    Great article. I’m working currently on this very same subject, and I’ve been working on creating a common Data Access Layer based on ObjectContext to allow easy data access using Linq to Entities.

    I’m using Generics to be able to perform CRUD operations on N-Layered applications with any defined Entities, so you have a "base" data access object, and inheriting from it using the entity type as type parameter you have full access to the base functionality. When I finish it I’ll publish an article on my blog.

    Stay tuned 😉

  10. This is my second post about &quot;Updating data using Entity Framework in N-Tier and N-Layer Applications&quot;

  11. This is my second post about &quot;Updating data using Entity Framework in N-Tier and N-Layer Applications&quot;

  12. ChrisMoses says:

    It looks like this extension will only work if the related end is not a collection.  Is that accurate, and, if so, do you have a version that would "Walk" then collection?  It would be really helpful.

  13. En esta ocasión, me voy a salir un poco de la línea regular que llevo en mi blog para hacer una pequeña

  14. This is my second post about &quot;Updating data using Entity Framework in N-Tier and N-Layer Applications&quot;.

Skip to main content