Entity framework 为什么DbSet.Add会更改其他实体的属性?

Entity framework 为什么DbSet.Add会更改其他实体的属性?,entity-framework,ef-code-first,entity-framework-6,Entity Framework,Ef Code First,Entity Framework 6,我有一个罕见的例子,调用DbSet.Add()会更改DbSet中已有的其他实体的一些属性。不幸的是,这种情况很少发生,我仅有的证据是一些日志文件,所以我还不能在本地复制它 行为是这样的: 首先,我们使用LINQ查询从DbSet加载一些实体 然后,其中一些实体被更改。还没有SaveChanges() 现在我们通过调用DbSet.add()添加一些实体 步骤2的一些实体在步骤3中更改(它们的一个外键属性设置为null) 有什么想法吗?EF 6代码优先模型会发生这种情况吗 我能想到的唯一可能性是,Db

我有一个罕见的例子,调用
DbSet.Add()
会更改
DbSet
中已有的其他实体的一些属性。不幸的是,这种情况很少发生,我仅有的证据是一些日志文件,所以我还不能在本地复制它

行为是这样的:

  • 首先,我们使用LINQ查询从
    DbSet
    加载一些实体
  • 然后,其中一些实体被更改。还没有
    SaveChanges()
  • 现在我们通过调用
    DbSet.add()
    添加一些实体
  • 步骤2的一些实体在步骤3中更改(它们的一个外键属性设置为
    null

    有什么想法吗?EF 6代码优先模型会发生这种情况吗

    我能想到的唯一可能性是,
    DbContext
    刷新数据库中的一些数据,但我们现在不希望它这样做

    EDIT:由于我们几个星期以来一直在追踪这个bug,因此代码目前散布在日志语句中。以下是相关的代码部分:

    // parameter: List<Entry> entriesFromUser
    
    var entriesFromDb = db.Entries
        .Where(...)
        .OrderBy(...)
        .ToList();
    
    var newEntries = MergeEntries(entriesFromDb, entriesFromUser);
    
    var propertyBefore = entriesFromDb[0].MyForeignKeyId;
    for (var i = 0; i < newEntries.Count; i++)
    {
        // make sure that the "new entry" is not a modified one
        if (entriesFromDb.Contains(newEntries[i])
        {
            throw new Exception();
        }
    
        db.Entries.Add(newEntries[i]);
    }
    
    var propertyAfter = entriesFromDb[0].MyForeignKeyId;
    
    Debug.Assert(propertyBefore == propertyAfter);          // <=== fails sometimes
    
    db.SaveChanges();
    
    //参数:List entriesFromUser
    var entriesFromDb=db.Entries
    .其中(…)
    .OrderBy(…)
    .ToList();
    var newEntries=MergeEntries(entriesFromDb,entriesFromUser);
    var propertyBefore=entriesFromDb[0]。MyForeignKeyId;
    对于(var i=0;iDebug.Assert(propertyBefore==propertyAfter);//D'oh.找到了原因。希望对其他人有所帮助

    我们正在使用,这意味着我们同时拥有导航属性
    entry.MyForeignKey
    和外键属性
    entry.MyForeignKeyId
    ,这有很多优点,但也意味着在使用这个、那个属性时必须小心

    事实证明,我们在代码的深处有以下赋值,其中一个条目的所有数据都复制到另一个条目:

    entry.MyForeignKeyId = otherEntry.MyForeignKeyId
    entry.MyForeignKey = otherEntry.MyForeignKey
    
    但是,在许多情况下,您将外键值设置为实体的
    MyForeignKeyId
    ,但将属性
    MyForeignKey
    保留为null,因为未加载父实体。只要您不将null指定给实体的
    MyForeignKey
    属性,这就可以了,因为这样EF就会将
    MyForeignKeyId
    也设置为null


    因此,似乎在我们的代码将null分配给
    MyForeignKey
    之后,实体在内存中保留了null
    MyForeignKey
    和非null
    MyForeignKeyId
    DbSet
    注意到
    MyForeignKey
    收到了一个
    null
    赋值,因此
    DbSet
    继续并将
    null
    赋值给
    MyForeignKeyId

    请显示执行这些步骤的代码。我可以想象添加实体会改变FK值,但只有您的代码才能确认。呃嗯,是的,这并没有告诉我很多关于实体之间的关系。这里可能发生的是,一个新实体“窃取”了一个现有实体的引用。有关于这种“窃取引用”的文档吗?顺便说一句,我说的外键是N:1。你说的新实体“窃取”是什么意思来自现有实体的引用?是否记录了EF 6代码优先行为?如果现有B是现有a的子级,并且有一个新的C将B作为子级,则可能导致B获得不同的FK。