Methods to Attach Disconnected Entities in EF 6:

Here you will learn about different methods in Entity Framework 6.x that attach disconnected entity graph to a context.

Saving entity in disconnected scenario is different than in 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 context aware about these entities. Second, set 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.

attach disconnected entity graph

Entity Framework provides the following methods that attaches disconnected entities to a context and also set EntityState to each entity in of an entity graph.

  • DbContext.Entry()
  • DbSet.Add()
  • DbSet.Attach()

DbContext.Entry():

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 ability to perform action on 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 entire entity graph to a context with specified state to a parent entity and also sets diffent 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())
{
    //mark standard based on StandardId
    context.Entry(student).State = EntityState.Added; 

    foreach (var entity in context.ChangeTracker.Entries()){
        Console.WriteLine("{0}: {1}", item.Entity.GetType().Name, item.State);
    } 
}
Output:
Student: Added
Standard: Added
Course: Added
Course: Added

In the above example, the Studnet entity graph includes Standard and Course entities. context.Entry(student).State = EntityState.Added; sets Added state to parent entity as wel as all other child entities irespective of whether a child entity contains empty key value or not. Thus, it is recommanded to use Entry() method carefully.

The following table lists behaviour of Entry() method.

Parent Entity State Entity State of child entities
Added Added
Modified Unchanged
Deleted All child entities will be null

DbSet.Add():

The DbSet.Add() method attaches the entire entity graph to a context and automatically applies 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);
}
Output:
Student: Added
StudentAddress: Added

The DbSet.Add() method attach the entire entity graph to a context with Added state to each entity. Calling context.Savechanges() will execute INSERT command for all the entities, which will insert new records in the appropriate database table.

DbSet.Attach():

The DbSet.Attach() method attaches an entire entity graph to the new context with 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);
}
Output:
Student: Unchanged
StudentAddress: Unchanged