25 July 2008

Linq - How to attach objects from different data contexts

After retrieving an object with Linq to Sql, if an update (Attach) is tried on the same object, the following exception is thrown:

An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.

Example:

Product product = null;
Product originalProduct = new Product();
 
// Gte product to change its properties
using (myDataContext dc1 = new myDataContext())
{
   product = dc1.Products.Single(p=>p.ID==457);
}
 
product.Description = "MyProduct";
 
using (myDataContext dc2 = new myDataContext())
{
   dc2.Products.Attach(product , originalProduct);
   dc2.SubmitChanges(); 
}

The best solution to fix this behavior is to set the DeferredLoadingEnabled property of the DataContext to false of the retrieve entity query.


Example:



Product product = null;
Product originalProduct = new Product();
 
// Gte product to change its properties
using (myDataContext dc1 = new myDataContext())
{
   dc1.Datacontext.DeferredLoadingEnabled = false;
   product = dc1.Products.Single(p=>p.ID==457);
}
 
product.Description = "MyProduct";
 
using (myDataContext dc2 = new myDataContext())
{
   dc2.Products.Attach(product , originalProduct);
   dc2.SubmitChanges(); 
}

 


The DeferredLoadingEnabled property of the DataContext controls the deferred loading options of LINQ.

2 comments:

Maxi Ng said...

if setting this to false, will it leads to reading all related data in a query for an entity?
I think MSDN say so and that will lead to a performace disaster.

Rui said...

When setting DeferredLoadingEnabled = false, LINQ doesn't automatically loads all entities associated to the given object.
It is necessary to explicitly configure LoadOptions (DataLoadOptions) for the data context manually.