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 methodObjectContext
will start tracking whole object graph (main entity and all related entities). All entities which were not tracked yet will be set toUnchanged
state.AddObject
- if you call this methodObjectContext
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 toAdded
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
Web App Blocked While Processing Another Web App on Sharing Same Session
How to Make a .Net Windows Forms Application That Only Runs in the System Tray
Prevent Caching in ASP.NET MVC for Specific Actions Using an Attribute
How to Properly Exit a C# Application
Vb.Net Equivalent for C# 'Dynamic' with Option Strict On
Async/Await With/Without Awaiting (Fire and Forget)
How to Create a Dto in C# ASP.NET from a Fairly Complex JSON Response
Most Common C# Bitwise Operations on Enums
Interop Type Cannot Be Embedded
Using Linq to Group a List of Objects into a New Grouped List of List of Objects
Specifying a Custom Datetime Format When Serializing with JSON.Net
Creating a Generic<T> Type Instance with a Variable Containing the Type
Detect If Running as Administrator with or Without Elevated Privileges
How to Know If a Process Is Running