Danil Sabirov
Danil Sabirov

Reputation: 353

Entity Framework: context.AddObject without adding masters

folks,

I have a problem when I'm creating new object that has master. The problem actually is that EF is trying to create master object too, but I don't need it.

My two poco classes look like:

[DataContract(IsReference = true)]
public class Application
{
    [DataMember]
    public int ID { get; set; }

    [DataMemeber]
    public int ProjectManagerId {get; set; }

    [DataMember]
    public ProjectManager PM { get; set;}
}

[DataContract(IsReference = true)]
public class ProjectManager
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string FullName { get; set; }

}

When I'm creating new object on ASP.NET MVC page, I've got object of Application class, that has ProjectManagerId equals to 1 and PM field with ID = 0 and FullName for example 'Forest Gump'.

So, when I'm adding object, I have exception that application.PM.ID cannot be 0:

context.Applications.AddObject(application); 
context.SaveChanges();

Is it possible to addobject my object without adding master?

I found workaround, but I don't like it: it is assigning PM field to null before adding object to context

application.PM = null;

Upvotes: 3

Views: 885

Answers (1)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364369

EF has one core rule you must be aware of. It works with whole object graph and it doesn't allow combining detached and attached entities in the same object graph. It means that both Attach and AddObject method will be always executed on all entities in the object graph (it will traverse your navigation properties and execute the operation recursively).

Because of this essential behavior you must handle existing objects manually. You have three options:

Don't use navigation property. Your Application class has ProjectManagerId exposed. You need only to set this property to ID of the existing manger without populating ProjectManager navigation property to build a relation.

var application = new Application { ProjectManagerId = 1 };
context.Applications.AddObject(application);
context.SaveChanges();

Attach your parent, add child and only after that make connection between them:

// Create attached existing project manager
var projectManager = new ProjectManager { ID = 1 };
context.ProjectManagers.Attach(projectManager);

// Create a new added application
var application = new Applications();
context.Applications.AddObject(application);

// Now you are making relation between two entities tracked by the context
application.ProjectManager = projectManager;  
context.SaveChanges();

The last option is simply fixing the state of existing entities. In this case you will set project manger to be unchanged while application will still remain in the added state:

// Add application and its related project manager
context.Applications.AddObject(application);
context.ObjectStateManager.ChangeObjectState(application.ProjectManager, EntityState.Unchanged);
context.SaveChanges();

Upvotes: 4

Related Questions