Entity Framework: 使用本地对象设置导航属性(尚未保存到数据库)

Entity Framework: Set navigation property with a local object (not saved to the database yet)

我正在使用 Entity Framework 版本 6,需要在很短的时间内将数千个对象批量插入数据库。

因此我将 DbContext.Configuration.AutoDetectChangesEnabled 更改为 false 并且仅在添加了许多项后才使用 SaveChanges

这个实体,我们称它为 Person,有一个导航 属性 到它自己,例如。 G。 Supervisor.

现在我想将一个人添加到数据库中,并想用迭代前刚刚添加到上下文(只是本地,不在数据库中)的主管填充导航 属性。

由于性能原因,我只是在 200 万人之后调用 SaveChanges()。如果我在 SaveChanges 之后查看数据库,列 Supervisor 始终为 NULL。如何添加导航属性?

奇怪的是,我的实体模型有四个导航属性,分别名为 Supervisor1Supervisor2Supervisor11Supervisor3。为什么实体模型为一个数据库约束创建四个导航属性?

详细解释我的问题:这是我的 database structure. EntityFramework creates this model.

有一个循环来处理来自 csv 文件的数据:

     db.DbContext.Configuration.AutoDetectChangesEnabled = false; // for performance
    ///...    
    while (!parser.EndOfData)
    {                  
    // process data from a csv file with a name and a supervisorId             
        db.AddNewPerson(name, supervisorId);
    }
    db.SaveChanges();
    db.DbContext.Configuration.AutoDetectChangesEnabled = true;

这是数据访问层方法:

public void AddNewPerson(string name, long? supervisorId)
    {
        var dbSetPerson = dbContext.Set<Person>();
        var newPerson = new Person(name);
        dbSetPerson.Add(newPerson);

        if (supervisorId != null)
        {
            var supervisor = dbSetPerson.Local.FirstOrDefault(x => x.PersonId == supervisorId); // first look if the supervisor was just processed in this loop
            if (supervisor == null)
                supervisor = dbSetPerson.FirstOrDefault(x => x.PersonId == supervisorId); // if the was no person found look in the database
            if (supervisor != null)
                newPerson.Person2 = supervisor;
        }
    }

提前感谢您的帮助!

我认为你的问题是,实体在这个阶段没有存储到数据库中,EF(代理)不知道它。您可以做的是在调用 StoreChanges():

之后附加它
yourContext.Persons.Attach(justAddedPerson);

但是当你添加一些代码时,我可以给出更具体的答案。

更新 根据您的编辑(我猜 ID 是整数而不是自动创建的)我建议如下:

var persons = new List<Person>();
while (!parser.EndOfData)
{
    var person = new Person { Name = parser... }
    person.SupervisorId = parser...
    list.Add(person);
}

dbSet.AddRange(persons);

dbContext.SaveChanges();

先做解析,再做数据库操作。 EF 足够聪明,可以在您不更改配置时设置导航属性,这不再是必需的,因为 AddRange() 应该比 Add() 快得多,因为它只调用 detectchanges 一次。通过仅设置主管 ID,