【问题标题】:Cannot insert explicit value for identity column when IDENTITY_INSERT is set to OFF. (Entity Framework Core)当 IDENTITY_INSERT 设置为 OFF 时,无法为标识列插入显式值。 (实体框架核心)
【发布时间】:2019-11-29 15:17:22
【问题描述】:

当我尝试将新实体添加到数据库中时出现此错误。实体名称为DestuffedContainer。该实体及相关实体的定义如下:

DestuffedContainer:

[Table("DestuffedContainer")]
public class DestuffedContainer
{
    public long DestuffedContainerId { get; set; }
    public int Index { get; set; }
    public string Description { get; set; }
    public int? PackageQuantity { get; set; }
    public string PackageType { get; set; }
    public double? CBM { get; set; }
    public string Location { get; set; }
    public string MarksAndNumber { get; set; }
    public int? ManifestWeight { get; set; }
    public int? FoundWeight { get; set; }
    public int? ManifestQuantity { get; set; }
    public string ConsigneeName { get; set; }
    public string Remarks { get; set; }
    public string InvoiceFound { get; set; }
    public string PackageFound { get; set; }
    public long TellySheetId { get; set; }
    public TellySheet TellySheet { get; set; }
    public long ContainerIndexId { get; set; }
    public ContainerIndex ContainerIndex { get; set; }
}

电视片:

[Table("TellySheet")]
public class TellySheet
{
    public TellySheet()
    {
        DestuffedContainers = new List<DestuffedContainer>();
    }

    public long TellySheetId { get; set; }
    public string TellyClerk { get; set; }
    public DateTime? DestuffDate { get; set; }
    public string DayNight { get; set; }
    public long ShippingAgentId { get; set; }
    public ShippingAgent ShippingAgent { get; set; }

    public List<DestuffedContainer> DestuffedContainers { get; set; }
}

容器索引:

[Table("ContainerIndex")]
public class ContainerIndex
{
    public long ContainerIndexId { get; set; }
    public string BLNo { get; set; }
    public int? IndexNo { get; set; }
    public double? BLGrossWeight { get; set; }
    public string Description { get; set; }
    public string MarksAndNumber { get; set; }
    public string ShippingLine { get; set; }
    public bool? IsDestuffed { get; set; }
    public string AuctionLotNo { get; set; }
    public long? ContainerId { get; set; }

    public Container Container { get; set; }
    public DeliveryOrder DeliveryOrder { get; set; }
    public OrderDetail OrderDetail { get; set; }
    public DestuffedContainer DestuffedContainer { get; set; }
    public Auction Auction { get; set; }
}

当我尝试添加去塞容器列表时,以下代码行中出现错误:

 var dstfContainers = new List<DestuffedContainer>();
 _tellySheetRepo.Add(tellySheet);

 foreach (var container in containers)
 {
     var destuff = new DestuffedContainer
            {
                TellySheetId = tellySheet.TellySheetId,
                ContainerIndexId = container.ContainerIndexId,
                Index = container.IndexNumber ?? 0,
                Description = container.Description,
                PackageQuantity = container.Package,
                PackageType = container.PackageType,
                CBM = container.CBM,
                ManifestWeight = container.ManifestWeight > 0 ? Convert.ToInt32(container.ManifestWeight) : 0,
                FoundWeight = container.FoundWeight > 0 ? Convert.ToInt32(container.FoundWeight) : 0,
                MarksAndNumber = container.MarksAndNumber,
                Location = container.Location,
                Remarks = container.Remarks,
                InvoiceFound = container.InvoiceFoud,
                PackageFound = container.PackageFoud
            };

    dstfContainers.Add(destuff);

    var index = _cIndexRepo.Find(container.ContainerIndexId);

    if (index != null)
    {
        index.IsDestuffed = true;
        _cIndexRepo.Update(index);
    }
}

_destuffRepo.AddRange(dstfContainers);

我不确定这个错误是什么意思,因为我没有明确指定 destuffedcontainer 实体的主键值,默认情况下它是 0。实体框架应该将其作为插入项选择,但它会引发错误。

几天前它工作正常,但我不确定自从导致此错误后发生了什么变化。

我正在使用 Entity Framework Core 对我的实体进行建模。我尝试了几种解决方案,但似乎都没有奏效。对于解决此问题的任何帮助,我将不胜感激。

编辑

似乎当我将 DestuffedContainer 表中的外键 ContainerIndexId 值分配给实体时,出现此错误。我不确定它是如何相关的。

【问题讨论】:

  • 如果您将 ID 列命名为 Id 而不是 TellySheetId 等,它是否有效?
  • It was working fine few days ago 你能用git 显示过去几天发生了什么变化吗?
  • 我的代码存储库位于 Azure DevOps 中。我将更改 Destuffed Container 实体的主键 Id 名称,看看它是否有效。
  • 不——还是同样的错误。
  • “当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'DestuffedContainer' 中插入标识列的显式值。”这是我看到的错误。

标签: c# asp.net-core entity-framework-core


【解决方案1】:

为未来的读者。

我遇到了相反的问题。我不希望 IDENTITY 自动开启。

所以是这样的:(非常简单的流畅映射)

        builder.HasKey(ent => ent.MyColumnWhichIsTheKey);

我必须添加这一行 (ValueGeneratedNever) 以保持 IDENITY 处于关闭状态(故意“关闭”):

        builder.HasKey(ent => ent.MyColumnWhichIsTheKey);
        builder.Property(ent => ent.MyColumnWhichIsTheKey).ValueGeneratedNever();

见:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.builders.propertybuilder.valuegeneratednever?view=efcore-3.1

其他提示:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.3" />

【讨论】:

    【解决方案2】:

    错误提示您无法在 IDENTITY 列中插入数据,因为这样做已被禁用。

    您可以通过执行此操作来启用此行为

    SET IDENTITY_INSERT [ [ database_name . ] schema_name . ] table_name { ON | OFF }
    

    MSDN link

    当您使用实体框架核心时,您必须:

    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.DestuffedContainer ON");
    context.SaveChanges();
    context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.DestuffedContainer OFF");
    

    > Explicit values into SQL Server IDENTITY columns

    编辑很抱歉,我未能理解您没有提供价值。

    然后确保您的列被标记为模型的 IDENTITY。我看到您正在使用属性来告诉 efcore 如何命名您的表。只要您的关键属性不使用传统的 Id 名称,您就需要在实体类上使用 [Key] 属性使其明确,例如:

    [Key]
    public long DestuffedContainerId { get; set; }
    

    或者在你的上下文类中使用 FluentAPI:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
     ...
        modelBuilder
        .Entity<DestuffedContainer>()
        .Property(d => d.DestuffedContainerId)
        .ValueGeneratedOnAdd() 
    
        modelBuilder
        .Entity<DestuffedContainer>()
        .HasKey(d => d.DestuffedContainerId)
     ...
    }
    

    还要检查 sql server 表定义,并确保将命名为您的属性的字段设置为 IDENTITY,这肯定会给出您得到的错误,但值得检查。

    【讨论】:

    • 谢谢。为什么主键是自动生成的字段时需要启用身份插入,为什么只有这个表?
    • 哦,我看到你没有指定值,重新访问你的代码,错误显示你是。如果该属性实际上是表的 IDENTITY,请与 SQL 管理工作室核实。此外,您需要使用 [Key] 属性显式标记您的 Identity 属性,或者在您的 dbcontext 类中使用 FluentApi modelBuilder.Entity&lt;DestuffedContainer&gt;().Property(d =&gt; d.DestuffedContainerId).ValueGeneratedOnAdd()modelBuilder.Entity&lt;DestuffedContainer&gt;().HasKey(d =&gt; d.DestuffedContainerId) 的覆盖,因为它不遵循约定(未命名为 Id
    【解决方案3】:

    以防有人在 2021 年发现此问题,使用 EF Core 5.x,我为此苦苦挣扎了几个小时,经过大量搜索后仍未找到我的解决方案。

    在我的例子中,我有一个现有的数据库并使用 EF Core 脚手架命令为我创建 DB 上下文和关联的模型类。当尝试像这样将新的 TimeEntry 插入数据库中的 TimeEntry 表时:

    TimeEntry timeEntry = new TimeEntry
            {
                EmployeeId = Emp.Id,
                ScheduleTypeId = SchedTypeId,
                FacilityId = FacilityId,
                DateTimeIn1 = DateTimeIn1,
                DateTimeIn2 = DateTimeIn2,
                DateTimeIn3 = DateTimeIn3,
                DateTimeIn4 = DateTimeIn4,
                DateTimeIn5 = DateTimeIn5,
                DateTimeIn6 = DateTimeIn6,
                DateTimeIn7 = DateTimeIn7,
                DateTimeOut1 = DateTimeOut1,
                DateTimeOut2 = DateTimeOut2,
                DateTimeOut3 = DateTimeOut3,
                DateTimeOut4 = DateTimeOut4,
                DateTimeOut5 = DateTimeOut5,
                DateTimeOut6 = DateTimeOut6,
                DateTimeOut7 = DateTimeOut7,
                Day1TotalHours = day1TotalHoursDecimal,
                Day2TotalHours = day2TotalHoursDecimal,
                Day3TotalHours = day3TotalHoursDecimal,
                Day4TotalHours = day4TotalHoursDecimal,
                Day5TotalHours = day5TotalHoursDecimal,
                Day6TotalHours = day6TotalHoursDecimal,
                Day7TotalHours = day7TotalHoursDecimal,
                WeekStartDate = StartDateForWeek,
                WeekTotalHours = WeekTotalHoursDecimal
            };
            db.TimeEntries.Add(timeEntry);
            db.SaveChanges();
    

    我收到此错误,即使我没有明确尝试插入 ID。经过多次尝试,我终于想出了如何解决它,尝试了我能找到的每个帖子中的所有内容,但没有任何效果。这段代码解决了我的 DbContext 类中 id 字段的问题:

    modelBuilder.Entity<TimeEntry>(entity =>
            {
                entity.ToTable("TimeEntry");
    
                entity.Property(e => e.Id).HasColumnName("id").ValueGeneratedOnAdd(); // <-- This fixed it for me
    

    另外请注意,在其他帖子之后,我也在我的 TimeEntry 模型类中设置了此设置,不确定是否重要以避免此错误:

    public partial class TimeEntry
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public int Id { get; set; } // rest of code removed for brevity
    

    我真的希望这对未来的人有所帮助,这让我发疯了。

    【讨论】:

      【解决方案4】:

      如果您想保持 Identity_Insert 关闭并允许手动插入,则比所选答案更好的解决方案 在您定义的应用程序上下文中的 OnModelCreating 方法中

      这是使用 EF Core for NET 5.0

            modelBuilder.Entity<EntityType>().HasKey(x => x.KeyWithIdentityValue);
            modelBuilder.Entity<EntityType>().Property(x => x.KeyWithIdentityValue).ValueGeneratedOnAdd();```
      

      【讨论】:

      • 他们已经有了(见评论),否则一开始就不会发生异常。
      • @GertArnold 我没有看到函数 ValueGeneratedOnAdd() 被调用,我也没有看到他定义了 Dbcontext 属性?现在我看到我的答案与 David Ayres 相同,正确的解决方案不应该是使用“ValueGeneratedNever()”,因为如果你愿意,你可以识别
      • EF 按照惯例将其作为标识列。
      猜你喜欢
      • 2016-05-13
      • 2021-05-15
      • 1970-01-01
      • 2017-10-26
      • 2020-06-06
      • 2019-03-10
      • 2014-05-24
      • 2018-06-29
      • 2016-08-18
      相关资源
      最近更新 更多