Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5

Working hard to enrich millions of peoples' lives

Sponsors

News

I was
Co-Founder and CTO of Pageflakes, acquired by LiveUniverse - founded by MySpace founder.

I am
Chief Architect, SaaS Platform, British Telecom

I will be
Chief Architect, Mi...

Follow omaralzabir on Twitter

My Public Page
www.pageflakes.com/omar

View Omar AL Zabir's profile on LinkedIn

Read my blog on:

Omar AL Zabir

www.oazabir.com



Views:

Open source projects

Linq to SQL: How to Attach object to a different data context

After upgrading to Visual Studio 2008 RTM, you will have trouble updating Linq to SQL Classes which are read from one data context and then updated into another data context. You will get this exception during update:

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

Here's a typical example taken from a Forum post:

   1: public static void UpdateEmployee(Employee employee)
   2: {
   3: using (HRDataContext dataContext = new HRDataContext())
   4: {
   5: //Get original employee
   6: Employee originalEmployee = dataContext.Employees.Single(e=>e.EmployeeId==employee.EmployeeId);
   7:  
   8: //attach to datacontext
   9: dataContext.Employees.Attach(employee, originalEmployee);
  10:  
  11: //save changes
  12: dataContext.SubmitChanges();
  13:  
  14: }
  15: }

When you call the Attach function, you will get the exception mentioned above.

Here's a way to do this. First, create a partial class that adds a Detach method to Employee class. This method will detach the object from it's data context and detach associated objects.

   1: public partial class Employee
   2: {
   3:   public void Detach()
   4:   {
   5:     this.PropertyChanged = null; this.PropertyChanging = null;
   6:  
   7:     // Assuming there's a foreign key from Employee to Boss
   8:     this.Boss = default(EntityRef<Boss>);
   9:     // Similarly set child objects to default as well
  10:  
  11:     this.Subordinates = default(EntitySet<Subordinate>);
  12:   }
  13: }
  14:  
  15:  

Now during update, call Detach before attaching the object to a DataContext.

   1: public static void UpdateEmployee(Employee employee)
   2: {
   3:     using (HRDataContext dataContext = new HRDataContext())
   4:     {
   5:         //attach to datacontext
   6:         employee.Detach();
   7:  
   8:         dataContext.Employees.Attach(employee);
   9:         //save changes
  10:  
  11:         dataContext.SubmitChanges();
  12:     }
  13: }
  14:  

This'll work. It assumes the employee object already has its primary key populated.

You might see during update, it's generating a bloated UPDATE statement where each and every property is appearing on the WHERE clause. In that case, set UpdateCheck to Never for all properties of Employee class from the Object Relational Designer.

Posted: Dec 08 2007, 07:00 PM by oazabir | with 10 comment(s)
Filed under: , ,

Comments

Christopher Steen said:

Link Listing - December 9, 2007

# December 10, 2007 1:17 AM

Munkie said:

Do you have a more elegant way of doing this?  Or perhaps a more lazy way, such as using reflection?

Still it seems quite disappointing that we have to come to this.

# January 2, 2008 12:26 PM

Fabricio Carvalho Ferreira said:

I'm facing the very same issue, and the approach above didn't work to me. Do you have any other suggestion to solve that? Currently what I'm doing is to get the original record from database within the update method, update the original record with data from the modified object, and then call the SubmitChanges. This is very inefficient ... I don't wanna do another round trip to database just to update a record.

# January 10, 2008 12:30 PM

Joel Wright said:

I'm doing the same thing using a bit of reflection:        

public void DetachRelatedModels()

       {

           Type ModelType = this.GetType();

           foreach (PropertyInfo Property in ModelType.GetProperties())

           {

               if (Property.GetCustomAttributes(typeof(AssociationAttribute), false).GetLength(0) > 0)

               {

                   Type PropertyType = Property.PropertyType;

                   Type[] ConstructorTypes = { };

                   ConstructorInfo PropertyConstructor = PropertyType.GetConstructor(ConstructorTypes);

                   object[] ConstructorValues = { };

                   object DefaultProperty = PropertyConstructor.Invoke(ConstructorValues);

                   Property.SetValue(this, DefaultProperty, null);

               }

           }

       }

# February 18, 2008 5:58 AM

Alkampfer’s Place » Blog Archives » Linq to Sql,working with detatched object …….. said:

Pingback from  Alkampfer&#8217;s Place  &raquo; Blog Archives   &raquo; Linq to Sql,working with detatched object &#8230;&#8230;..

# March 1, 2008 2:09 AM

Stephen Edwards said:

Hi there,

I wrote an article on this that you might want to look at.

stephenedwards.virtualituk.com/.../datacontext-attach-problem

# June 30, 2008 7:44 AM

mpetito said:

I'm trying an approach similar to reflection but using the MetaModel provided by the DataContext.

See crefs.blogspot.com/.../detaching-linq-to-sql-entities.html

# August 24, 2008 9:51 PM

Gugu said:

Why can i have a method that tells me if an object with a certain primary key is attached or not to the stupid datacontext ????

Nooooooooo!!! Instead I have to detach everytime.

Stupid!!!

# November 27, 2008 7:29 AM

Linq to Sql Updates | keyongtech said:

Pingback from  Linq to Sql Updates | keyongtech

# January 22, 2009 3:49 AM

Eric J. Smith said:

PLINQO implements Detach functionality on your entities automatically as well as a ton of other features and enhancements.  If you are interested, check out http://www.plinqo.com

# May 4, 2009 6:18 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)