c# - Entity Framework 在两个不同的上下文中插入实体两次

标签 c# entity-framework entity-framework-core

我正在使用 Entity Framework Core 在数据库中存储对象图。在构建图表时,我会多次创建一个实体,将其存储到数据库中,然后释放上下文。但是,我遇到了一个问题,即 EFC 尝试插入连接到新实体时已插入的实体。这最好用代码来解释。这是一段简短的重现代码(这是直线代码,但是上下文的两种使用发生在代码中的不同时间和位置)。

在第二次调用 context.SaveChanges() 时,出现以下异常:

SqlException:

Cannot insert explicit value for identity column in table 'Namespace' when IDENTITY_INSERT is set to OFF.

当我查看正在执行的 SQL 时,它正在尝试再次插入命名空间实体,大概是因为 myType 正在保存到数据库并且它引用了 dbNamespace 实体。

// see if namespace is in the db and add it if not
string someNamespaceString = "foobar";
CodeDatabase.Models.Namespace dbNamespace;
using (var context = new CodeFactsContext())
{
    dbNamespace = context.Namespace.FirstOrDefault(ns => ns.Namespace1 == someNamespaceString);
    if (dbNamespace == null)
    {
        dbNamespace = new Namespace() { Namespace1 = someNamespaceString };
        context.Namespace.Add(dbNamespace);
    }
    context.SaveChanges();
}

// Type entity created somewhere from the code
var myType = new CodeDatabase.Models.Type()
{
    FullName = "foobar.mytype",
    ShortName = "mytype",
    Namespace = dbNamespace // this is already in the DB
};

// check if myType is in the db and add it if not
using (var context = new CodeFactsContext())
{
    var dbType = context.Type.FirstOrDefault(t => t.FullName == myType.FullName);
    if (dbType == null)
    {
        dbType = myType;
        context.Add(dbType);
    }
    context.SaveChanges(); // throws exception
}

知道如何让 EF Core 识别(在第二个 context.SaveChanges() 中)应将 myType 插入数据库,但是 myType .Namespace 不应该因为它已经存在了吗?这两个实体都有一个由数据库自动生成的 int id,并且命名空间的 id 在第一次调用 SaveChanges 后设置为数据库值。我认为 EF Core 会识别出 id 不为 0 并且不会尝试保存它。非常欢迎任何帮助/建议。

最佳答案

I thought EFC would recognize that the id is not 0 and not try to save it.

问题是您正在使用 Add 方法,该方法将所有可访问且未跟踪的实体标记为新实体,无论键值如何(这是为了允许身份插入场景)。 Disconnected Entities - Working with graphs - All new/all existing entities 对此进行了解释。 。当你的场景落入Mix of new and existing entities时.

Any idea how to get EFC to recognize (in the second context.SaveChanges) that myType should be inserted into the database, but myType.Namespace should not because it's already there? Both of the entities have an int id that is autogenerated by the DB and the id of Namespace is set to the database value after the first call to SaveChanges.

实际上,第二个文档链接中解释了一个简单的解决方案:

With auto-generated keys, Update can again be used for both inserts and updates, even if the graph contains a mix of entities that require inserting and those that require updating

其中“再次”指的是 Saving single entities :

The Update method normally marks the entity for update, not insert. However, if the entity has a auto-generated key, and no key value has been set, then the entity is instead automatically marked for insert.

幸运的是,您的实体使用自动生成的 key ,因此只需使用 Update 而不是 Add:

if (dbType == null)
{
    dbType = myType;
    context.Update(dbType); // <--
}

关于c# - Entity Framework 在两个不同的上下文中插入实体两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53749244/

相关文章:

c# - EF Core 7 - 仅包含未删除的项目

c# - 您如何正确处理 Entity Framework Core 中的 SQL_VARIANT?

c# - 在 switch 语句中针对枚举进行编程,这是您的方式吗?

javascript - 使用 ASP 控件复选框隐藏表行

c# - 在时间范围内对获取项目进行分组

.net - DB2 查询偶尔得到 SQL0925N : Processing cancelled due to interrupt error

c# - 不了解 DbContext——每个应用程序或每个模型

c# - 如何使用 EFC 和 SQLite 避免使用 AUTOINCRMENT 关键字?

c# - 在 asp.net 中设置表单元素的默认值

c# - MVVM 可以在 View 中命令控件吗?