ADO.NET Entity Framework: Reattaching detached objects in short Lived contexts

Most enterprise applications uses an architectural pattern that needs a stateless facade for its business logic. So they can use it in several scenarios like WebServices or WCF, ASP.NET applications, Traditional Desktop Application (Windows Forms, WPF).. etc.


If you’re using Entinty Framework, your derived ObjectContext is called short lived context and there is some issues about it. My last post (in spannish language) explores best practices for better perfomance with short lived contexts in Entity Framework.


In this post I speak about re-attach modified EntityObjects, that were updated outside of an ObjectContext (in detached state). This is a very common scenario when you’re using stateless facades.


So, imagine that your facade retrieves an EntityObject of your model and passes it to some visual control in the user interface. When an user or a process in IU changes your EntityObject, this object is in a detached state, so there isn’t an ObjectStateManager tracking changes. When your passes it again to the facade at your Business Logic Layer this object needs to be persisted. Problem is that the new ObjectContext doesn’t know about changes in properties, so when you call SaveChanges() nothing happens.


At User Interface layer:


MyEntity entity = Facade.GetEntityById(1); 
BindEntitiesToControls();


(User interaction that changes values in the detached object, by example a roundtrip in an ASP.NET app. The entity object could be in the viewstate or HttpSession) 


entity.PropertyValue = 4; 


(User clicks «Save» button)


Facade.Save(entity); 


At Business Layer Facade (naive aproximation):


public static void Save(EntityObject entity)
{
   using(MyContext ctx = new MyContext)
   {
     ctx.Attach(entity);
     ctx.SaveChanges();
   } 
}


This aprox. does NOT work!!! because the ObjectContext unknowns the changes ocurred in entity object when it was detached.


Upsss, but this is a very common scenario, so what can i do?


Take a look to this extensor method for an ObjectContext:


/// <summary>
/// Attach an EntityObject that was modified when detached
/// </summary>
/// <param name=»obj»></param>
/// <param name=»objectDetached»>DetachedObject</param>

public static void AttachUpdated(this ObjectContext obj, EntityObject objectDetached)
{
  
if (objectDetached.EntityState == EntityState.Detached)
  
{
     
object original = null;
     
if (obj.TryGetObjectByKey(objectDetached.EntityKey, out original))
         
obj.ApplyPropertyChanges(objectDetached.EntityKey.EntitySetName, objectDetached);
      
else
      
throw new ObjectNotFoundException();
   
}
}

This extensor method first tries to load original entity into the object cache. If it’s already loaded, nothing happens; if not, it is retrieved from the storage.
Then applies the objectDetached properties to the original object retrieved in last step.


Our new facade method could be:


public static void Save(EntityObject entity)
{
   using(MyContext ctx = new MyContext)
   {
     ctx.AttachUpdated(entity);
     ctx.SaveChanges();
   } 
}
 

2 comentarios sobre “ADO.NET Entity Framework: Reattaching detached objects in short Lived contexts”

Responder a anonymous Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *