Skip to main content

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

Avatar

Cesar

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

Avatar
Cesar De la Torre

Principal Program Manager, .NET

Follow Cesar   

No Comments.