简体   繁体   中英

Why I can't add newly created principal entity when use DbSet.Add()?

I have two classes and they are in one to one relationship

public class Car
{
    public long Id { get; set; }
    public string Name { get; set; }
    public long CompanyId { get; set; }
    public Company Company { get; set; }
}

public class Company
{
    public long Id { get; set; }
    public string Name { get; set; }
    public Car Car { get; set; }
}

and let's say I have added one record (with id = 1) to the Company table, so now I want to add a new Car record as

Car c = new Car { Name = "car1" };
c.CompanyId = 1;
context.Cars.Add(c);
context.SaveChanges();

above approach works, I'm OK with that, but if I try the following approach, then it doesn't work and throw an exception(cannot add explicit value to identify column:

Car c = new Car { Name = "car1" };
Company com = new Company { Id = 1 };
c.Company = com;
context.Cars.Add(c);
context.SaveChanges();

so why DbSet.Add() thinks I'm adding a new Company record? can't it be smart enough to tell that there is already a company record whose id is 1 in the Company table?

It's because by default the Entity framework tries to add two objects to the database with a relationship between them when you are creating a relationship between two new objects. You can prevent adding child objects with the:

context.Entry(com).State = EntityState.Detached

or you can just try

Car c = new Car { 
    Name = "car1",
    Company = context.Companies.First(x => x.Id == 1)
};

context.Cars.Add(c);
context.SaveChanges();

The DbContext instance will add the relationships on the entity as added (new) items in the database which will be added when the changes are persisted ( SaveChanges ). You can manually change the state back to Unchanged for any entity that does not have changes.

Car c = new Car { Name = "car1" };
Company com = new Company { Id = 1 };
c.Company = com;
context.Cars.Add(c);

// mark the company as unchanged
context.Entry(com).State = EntityState.Unchanged;

context.SaveChanges();

Alternatively you can query the DbContext for an instance of Company and use that but this is 1 extra roundtrip to the database. The upside of this approach is the code might be easier to read/maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM