Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 4 - AddObject vs Attach

People also ask

What are the differences between ADD and attach?

Add is to indicate to the Entity Framework that we are going to want to insert a new record in the database. In contrast, Entry and Attach are used in scenarios where the record already exists in the database, and we simply want to make some kind of modification on it. var attach = context.

Why use Entity Framework attach?

Attach is used to repopulate a context with an entity that is known to already exist in the database. SaveChanges will therefore not attempt to insert an attached entity into the database because it is assumed to already be there.


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();

This is a late response but it might help others that find this.

Basically, a "disconnected" entity can happen when you manipulate an entity outside of the "using" scope.

Employee e = null;

using (var ctx = new MyModelContainer())
{
     e = ctx.Employees.SingleOrDefault(emp => emp .....);
}

using (var ctx2 = new MyModelContainer())
{
     e; // This entity instance is disconnected from ctx2
}

If you enter another "using" scope then the "e" variable will be disconnected because it belongs to the previous "using" scope and since the previous "using" scope is destroyed then "e" is disconnected.

That's how I understand it.


This is a quote from Programming Entity Framework: DbContext

Calling Remove on an entity that isn’t tracked by the context will cause an InvalidOperationException to be thrown. The Entity Framework throws this exception because it isn’t clear whether the entity you are trying to remove is an existing entity that should be marked for deletion or a new entity that should just be ignored. For this reason, we can’t use just Remove to mark a disconnected entity as Deleted; we need to Attach it first.

private static void TestDeleteDestination()
{
    Destination canyon;
    using (var context = new BreakAwayContext())
    {
        canyon = (from d in context.Destinations
        where d.Name == "Grand Canyon"
        select d).Single();
    }
    DeleteDestination(canyon);
}
private static void DeleteDestination(Destination destination)
{
    using (var context = new BreakAwayContext())
    {
        context.Destinations.Attach(destination);
        context.Destinations.Remove(destination);
        context.SaveChanges();
    }
}

The TestDeleteDestination method simulates a client application fetching an existing Destination from the server and then passing it to the DeleteDestination method on the server. The DeleteDestination method uses the Attach method to let the context know that it’s an existing Destination. Then the Remove method is used to register the existing Destination for deletion