Understanding Attaching/Detaching Objects in LINQ to SQL and in the Entity Framework

LINQ to SQL and the Entity Framework are very powerful tools, however as in many other useful tools there are some things you should be aware of when working with them. One of those things is object attaching and detaching. Let’s have a concrete example.

As you already know, you can retrieve an object from the database, update or remove it and all the necessary changes will be submitted to the database.

But what if you don’t want to perform additional SELECT query? Instead, you want just to perform one necessary query, either to update an object or remove it.

Well, a quite logical idea is to create an object, set an appropriate ID attribute and then update/delete it:

NorthwindDataContext db = new NorthwindDataContext();
 
Product product = new Product { ProductID = 1 };
 
db.Products.DeleteOnSubmit(product);
 
db.SubmitChanges();

 

Okay, but it won’t work. The code will gets compiled, but when executed it will throw an exception stating: “Cannot remove an entity that has not been attached.” Well, in fact, it’s quite obvious, because the object context is simply unaware of that object, so let it know about the object. We just need to attach the object to the object context:

NorthwindDataContext db = new NorthwindDataContext();
 
Product product = new Product { ProductID = 1 };
db.Products.Attach(product); //that necessary line
 
db.Products.DeleteOnSubmit(product);
 
db.SubmitChanges();

So, if you compile it now, you will get no exceptions and the necessary product will be removed from the database. You can use the same technique when you need to update an object without having to retrieve it from the database and the same thing applies to the Entity Framework, although the code is slightly different:

NorthwindEntities db = new NorthwindEntities();

Product product = new Product { ProductID = 10 };
product.EntityKey = new EntityKey("NorthwindEntities.Products", "ProductID", 10);
db.Attach(product);

db.DeleteObject(product);

db.SaveChanges();

Mike Borozdin

Thursday, January 15, 2009

blog comments powered by Disqus