Here you will learn about different methods in Entity Framework 6.x that attach disconnected entity graphs to a context.
Saving an entity in the disconnected scenario is different than in the connected scenario. There are two things we need to do when we get a disconnected entity graph or even a single disconnected entity.
First, we need to attach entities with the new context instance and make the context aware about these entities. Second, set an appropriate EntityState
to each entity manually because the instance doesn't know anything about the operations performed on the disconnected entities, so it cannot apply the appropriate EntityState
automatically.
The following figure illustrates this process.
Entity Framework provides the following methods that attach disconnected entities to a context and also set the EntityState
to each entity in an entity graph.
The Entry()
method of DbContext
class returns an instance of DbEntityEntry
for the specified entity.
The DbEntityEntry
object provides various information about the specified entity and also the ability to perform an action on the entity.
Most importantly, we can change the EntityState
of the specified entity using State
property, as shown below.
context.Entry(entity).state = EntityState.Added/Modified/Deleted
The Entry
method attaches an entire entity graph to a context with the specified state to a parent entity and also sets a different EntityState
to other entities. Consider the following example.
var student = new Student() { //Root entity (empty key) StudentName = "Bill", StandardId = 1, Standard = new Standard() //Child entity (with key value) { StandardId = 1, StandardName = "Grade 1" }, Courses = new List<Course>() { new Course(){ CourseName = "Machine Language" }, //Child entity (empty key) new Course(){ CourseId = 2 } //Child entity (with key value) } }; using (var context = new SchoolDBEntities()) { context.Entry(student).State = EntityState.Added; foreach (var entity in context.ChangeTracker.Entries()){ Console.WriteLine("{0}: {1}", entity.Entity.GetType().Name, entity.State); } }
In the above example, the Studnet
entity graph includes the Standard
and Course
entities.
context.Entry(student).State = EntityState.Added;
sets the Added state to the parent entity as well as to all other child entities
irrespective of whether a child entity contains an empty key value or not. Thus, it is recommended to use the Entry()
method carefully.
The following table lists the behaviour of the Entry()
method.
Parent Entity State | Entity State of child entities |
---|---|
Added | Added |
Modified | Unchanged |
Deleted | All child entities will be null |
The DbSet.Add()
method attaches the entire entity graph to a context and automatically applies the Added state to all entities.
//disconnected entity graph Student disconnectedStudent = new Student() { StudentName = "New Student" }; disconnectedStudent.StudentAddress = new StudentAddress() { Address1 = "Address", City = "City1" }; using (var context = new SchoolDBEntities()) { context.Students.Add(disconnectedStudent); // get DbEntityEntry instance to check the EntityState of specified entity var studentEntry = context.Entry(disconnectedStudent); var addressEntry = context.Entry(disconnectedStudent.StudentAddress); Console.WriteLine("Student: {0}", studentEntry.State); Console.WriteLine("StudentAddress: {0}", addressEntry.State); }
The DbSet.Add()
method attaches the entire entity graph to a context with the Added state to each entity.
Calling context.Savechanges()
will execute the INSERT command for all the entities, which will insert new records in the appropriate database table.
The DbSet.Attach()
method attaches an entire entity graph to the new context with the Unchanged entity state.
//disconnected entity graph Student disconnectedStudent = new Student() { StudentName = "New Student" }; disconnectedStudent.StudentAddress = new StudentAddress() { Address1 = "Address", City = "City1" }; using (var context = new SchoolDBEntities()) { context.Students.Attach(disconnectedStudent); // get DbEntityEntry instance to check the EntityState of specified entity var studentEntry = context.Entry(disconnectedStudent); var addressEntry = context.Entry(disconnectedStudent.StudentAddress); Console.WriteLine("Student: {0}",studentEntry.State); Console.WriteLine("StudentAddress: {0}",addressEntry.State); }