RPM1984 RPM1984 - 9 days ago 4
C# Question

Entity Framework 4 - AddObject vs Attach

I have been working with Entity Framework 4 recently, and am slightly confused as to when to use ObjectSet.Attach, and ObjectSet.AddObject.

From my understanding:


  • Use "Attach" when an Entity already exists in the system

  • Use "AddObject" when creating a brand new Entity



So, if i'm creating a new Person, i do this.

var ctx = new MyEntities();
var newPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.AddObject(newPerson);
ctx.SaveChanges();


If i'm modifying an existing Person, i do this:

var ctx = new MyEntities();
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
existingPerson.Name = "Joe Briggs";
ctx.SaveChanges();


Keep in mind, this is a very simple example. In reality i am using Pure POCO's (no code generation), Repository pattern (don't deal with ctx.Persons), and Unit of Work (don't deal with ctx.SaveChanges). But "under the covers", the above is what happens in my implementation.

Now, my question - I am yet to find a scenario where i have had to use Attach.

What am i missing here? When do we need to use Attach?

EDIT

Just to clarify, i'm looking for examples of when to use Attach over AddObject (or vice-versa).

EDIT 2

The below answer is correct (which i accepted), but thought i'd add another example where Attach would be useful.

In my above example for modifying an existing Person, two queries are actually being executed.

One to retrieve the Person (.SingleOrDefault), and another to perform the UPDATE (.SaveChanges).

If (for some reason), i already knew that "Joe Bloggs" existed in the system, why do an extra query to get him first? I could do this:

var ctx = new MyEntities();
var existingPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.Attach(existingPerson);
ctx.SaveChanges();


This will result in just an UPDATE statement being executed.

Answer

ObjectContext.AddObject and ObjectSet.AddObject:
The AddObject method is for adding newly created objects that do not exist in the database. The entity will get an automatically generated temporary EntityKey and its EntityState will be set to Added. When SaveChanges is called, it will be clear to the EF that this entity needs to be inserted into the database.

ObjectContext.Attach and ObjectSet.Attach:
On the other hand, Attach is used for entities that already exist in the database. Rather than setting the EntityState to Added, Attach results in an Unchanged EntityState, which means it has not changed since it was attached to the context. Objects that you are attaching are assumed to exist in the database. If you modify the objects after they’ve been attached, when you call SaveChanges the value of the EntityKey is used to update (or delete) the appropriate row by finding its matching ID in the db table.

Furthermore, using the Attach method, you can define relationships between entities that already exist in the ObjectContext but that have not been connected automatically. Basically the main purpose of Attach, is to connect entities that are already attached to the ObjectContext and are not new so you cannot use Attach to attach entities whose EntityState is Added. You have to use Add() in this case.

For example, let's assume your Person entity has a navigation property named Addresses which is a collection of Address entity. Let's say you have read both Objects from context, but they are not related to each other and you want to make it so:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.PersonReference.Attach(existingPerson)
ctx.SaveChanges();
Comments