SET IDENTITY_INSERT TableName ON 在 Entity Framework Core 2.2 上不起作用

C1X*_*C1X 4 c# sql-server entity-framework-core aspnetboilerplate

我正在尝试将一条记录插入到自动生成 ID 的表中。出于这个原因,这是我的代码:

using (var context = new DbContext(GetConnection().Options))
{
    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Customers ON;");
    context.SaveChanges();
    context.Customers.Add(customer);
    context.SaveChanges();
    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Customers OFF;");
}
Run Code Online (Sandbox Code Playgroud)

但例外总是一样的:

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

我还尝试SET IDENTITY_INSERT dbo.Customers ON在 SQL Server Management Studio 中手动执行命令,并在执行上面的代码后,但抛出了相同的异常。

为什么?

Ser*_*dar 5

默认情况下,当您尝试为标识列插入值时,实体框架将抛出​​您遇到的错误。即使您启用identity_insert,它也将处于数据库级别而不是实体框架。

为了克服这个问题,您已经完成了第一步。但是作为第二步,您需要告诉 Entity Framework 这个字段是可插入的。你可以用 2 种不同的方式来做到这一点。

  1. 转到您的模型类,并添加[DatabaseGenerated(DatabaseGeneratedOption.None)]到您的身份列。使用此方法,您可以插入带有标识列的记录,而无需依赖于事务。

  2. 此外,您可以在同一个连接中执行整个代码。这样,当您尝试插入记录时,EF Core 不会抛出错误。请检查以下代码。

    using (var db = new Context())
    {
        db.Categories.Add(new Category
        {
            Id = 5,
            Name = "test"
        });
    
        db.Database.OpenConnection();
        try
        {
            db.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Categories ON;");
            db.SaveChanges();
            db.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Categories OFF;");
        }
        finally
        {
            db.Database.CloseConnection();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

更新

HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)也可以在仅使用实体框架时使用。Entity Framework Core Fluent API 没有实现HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).