Entity Framework 4 - Addobject VS Attach

Entity Framework 4 - AddObject vs Attach

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

In Entity Framework, what is the difference between Add and Attach and how can I solve my problem?

ObjectContext internally tracks all entities which was either loaded by context, attached or added. Only these entities can be modified in database when SaveChanges is invoked. Each such entity has a ObjectStateEntry in the ObjectStateManager. One of the main properties of the ObjectStateEntry is a State. The state is of enum type EntityState which offers these values:

  • Added
  • Deleted
  • Detached
  • Modified
  • Unchanged

Each entity loaded from the database is in Unchanged state. Detached is special state. You will not find ObjectStateEntry with Detached state in the ObjectStateManager. But if you ask ObjectStateManager for the ObjectStateEntry for entity not tracked by the context it will create a new ObjectStateEntry with Detached state.

Now the difference between Attach and AddObject:

  • Attach - if you call this method ObjectContext will start tracking whole object graph (main entity and all related entities). All entities which were not tracked yet will be set to Unchanged state.
  • AddObject - if you call this method ObjectContext will also start tracking whole object graph (main entity and all related entities). The difference is that all entities which were not tracked yet will be set to Added state (= new objects which must be set to database).

What's the different between AddObject and Attach when transfer a enttity from one context to another

The Attach method will attach the object or object graph in Unchanged state. That means if you don't do any modifications to the object after you attach it, EF will not issue any Update/Delete commands for that object when you call SaveChanges() method.

But when you use AddObject method EF will insert the object as a new entity in SaveChanges() method.

If the context2 is connected to a different database and you want to copy the instance then you can use AddObject. Otherwise use the Attach method.

Can we attach more than one object in entity framework and do savechanges once

Adding a new item and updating modified items is not really straightforward as just calling one method. You need to distinguish when you are adding a new item or when you are updating. But yes, you can submit multiple items to be updated or added as new. For example, this method can help you do both adding and updating of an entity:

public SomeEntity AddOrUpdate(SomeEntity item)
{
var original = _context.SomeDbSet.Local.FirstOrDefault(p => p.Id == item.Id)
?? _context.SomeDbSet.FirstOrDefault(p => p.Id == item.Id);

if (original != null) // Updating
{
var entry = _context.Entry(original);
entry.CurrentValues.SetValues(item);
}
else
{
// New item
item = _context.SomeDbSet.Add(item);
}

return item;
}

After a number of calls to this method, call SaveChanges on your DbContext-based object.

When to use DbSet T .Add() vs DbSet T .Attach()

Well, when you use Attach you tell the context that the entity is already in the database, SaveChanges will have no effect over attached entities. Add, on the other hand, changes the state of the entity in the context (if it's already there) to Added, meaning it will always insert the entity in the database when you call SaveChanges.

That's the difference.

What exactly does Attach() do in Entity Framework?

Just as a point of interest the code you have posted does nothing

using (var context = new MyEntities())
{
context.Attach(client);
context.SaveChanges();
}

All this does is attach the entity to the tracking graph make no modifications to the entity and save it.

Any changes made to the object before attach are ignored in the save

What would be more interesting is if it actually updated a property ie:

using (var context = new MyEntities())
{
context.Attach(client);
client.Name = "Bob";
context.SaveChanges();
}

ObjectSet T .AddObject() vs. EntityCollection T .Add()

No there is no way to make them behave the same. ObjectSet represents database query and once you use it you are always doing query to the database where your new team is not present yet. EntityCollection is local collection of loaded entities and if you use it you are doing query to your application memory.

Generally using EntityCollection is exactly same as maintaining separate List<Team>:

List<Team> teams = context.Teams.ToList();

var team = teams.FirstOrDefault(t => t.Name == newTeam.Name);
if (team == null)
{
context.Teams.AddObject(newTeam);
teams.Add(newTeam);
}

context.SaveChanges();

You can also use Dictionary<string, Team> and get probably better performance instead of searching the list for each team.



Related Topics



Leave a reply



Submit