繁体   English   中英

如何使用已存在于 EF 核心中的子实体保存实体?

[英]How to save an entity with a child entity which already exists in EF core?

我遇到了一个我从未见过的非常奇怪的问题。 我正在使用 .net CORE 3.0 + EF。 我有两个数据库模型,它们是

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Dog Dog { get; set; }
}

public class Dog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

所以,假设我的数据库中已经有一条 id=1 和 Name = "Bimbo" 的 Dog 记录。 现在,我想添加一个现有狗的人:

var p = new Person
{
    Name = "Peter",
    Dog = new Dog
    {
        Id = 1
    };
};

_dbContext.Persons.Add(p);

然后我得到

当 IDENTITY_INSERT 设置为 OFF 时,无法在表“Dogs”中插入标识列的显式值

我了解 EF 尝试将狗作为新记录插入,而我需要它将我的新 Person 记录与现有的 Dog 记录绑定。

我发现这个解决方案建议明确设置外键。 还有另一种方法吗? 还是处理这种情况的正确方法? EF Core 为标识列插入显式值

您可以将外键显式添加到人员

   public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int DogId {get;set;}
        public Dog Dog { get; set; }
    }

然后您可以将狗添加为参考而不将其加载到上下文中

var p = new Person
{
    Name = "Peter",
    DogId = 1
};

_dbContext.Persons.Add(p)

;

你有三个选项可以做到这一点

  1. 使用外键属性

    using ( var db = new MyDbContext(options) ) { var person = new Person { Name = "Paul", DogId = 1 }; db.Persons.Add(person); await db.SaveChangesAsync(); }
  2. 从上下文加载狗实例并使用该实例

    using ( var db = new MyDbContext(options) ) { var dog = db.Dogs.Find(1); var person = new Person { Name = "Paul", Dog = dog }; db.Persons.Add(person); await db.SaveChangesAsync(); }
  3. 创建具有显式 ID 的 dog 实例并将其附加到上下文

    using ( var db = new MyDbContext(options) ) { var dog = new Dog { Id = 1 }; db.Attach(dog); var person = new Person { Name = "Paul", Dog = dog }; db.Persons.Add(person); await db.SaveChangesAsync(); }

请参阅.net fiddle上的工作示例

当您将 Person object 添加到上下文时,EF 将其 state 以及它引用的具有主键集的任何 object 设置为已添加(如此所述)。 这就是为什么 EF 尝试将新的 Dog object 插入到具有新 id 的数据库中,而异常指出 Dogs 表的 id 是由数据库生成的。

要解决此问题,您可以手动将新 Dog object 的 state 设置为 Unchanged,这将阻止 EF 将新记录插入数据库。:

_dbContext.Entry(person.Dog).State = EntityState.Unchanged

更好的解决方案是将 DogId 属性添加到 Person object 并设置它,而不是创建新的 Dog 实例或从数据库加载 Dog object 并将其设置为 Person ZA8CFDE6331BD59EB2AC96F8911C4B666 中建议的 Dog 属性.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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