【问题标题】:SET IDENTITY_INSERT TableName ON does not work on Entity Framework Core 2.2SET IDENTITY_INSERT TableName ON 在 Entity Framework Core 2.2 上不起作用
【发布时间】:2019-11-13 16:36:28
【问题描述】:

我正在尝试将记录插入到具有自动生成 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;");
}

但例外总是一样的:

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

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

为什么?

【问题讨论】:

  • 为什么您需要提供显式值吗? IDENTITY 列的全部意义在于您不必担心提供正确的值 - SQL Server 将为您处理......
  • 同意,您的要求没有任何意义。为什么不能让数据库生成值?如果您出于某种原因不希望这样做,请不要使用 IDENTITY 列

标签: c# sql-server entity-framework-core aspnetboilerplate


【解决方案1】:

默认情况下,当您尝试为标识列插入值时,Entity Framework 会抛出一个错误。即使您启用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();
        }
    }
    

更新

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

【讨论】:

  • 嗨@Serdar,我在我的映射中找不到HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)。 (我的意思是modelBuilder.Entity<Customer>().Property(x => x.Id). ??
  • 而我无法插入 [DatabaseGenerated(DatabaseGeneratedOption.None)],因为 Id 字段是从抽象类继承而来的
  • 看起来 EF Core 中不支持 HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)。我有另一个更干净的建议。请检查更新。
  • 如果我像您的实现一样使用 BeginTransaction(),则不会显示错误,但没有记录保存在数据库中。如果我在 db.SaveChanges() 之前添加 tran.commit() 它会显示相同的错误:当 IDENTITY_INSERT 设置为 OFF 时,无法在表“客户”中插入标识列的显式值
  • 我相信我犯了一个错误,整体没有在同一个事务中执行。您可以通过在同一连接中执行整个代码来获得相同的结果。我更新了答案中的代码。请看一看。它已经过测试并且绝对有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-10
  • 2023-03-14
  • 2012-08-13
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多