实体框架抛出无法在表中插入标识列的显式值...当 IDENTITY_INSERT 设置为 OFF 错误

Posted

技术标签:

【中文标题】实体框架抛出无法在表中插入标识列的显式值...当 IDENTITY_INSERT 设置为 OFF 错误【英文标题】:Entity Framework Throwing Cannot Insert Explicit Value for Identity Column In Table ... When IDENTITY_INSERT is set to OFF Error 【发布时间】:2014-05-24 08:48:02 【问题描述】:

我正在使用 Microsoft SQL Server 2008 R2 并拥有三个相关表: 转换碳水化合物、国家和州省

使用 EF Power Tools,我对数据库 (http://msdn.microsoft.com/en-us/data/jj593170.aspx) 进行了逆向工程,并尝试使用实体框架将记录插入到 ConvertCarb 表中。

但是,程序在尝试保存更改时抛出以下错误:

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

这是运行时代码:

var convertCarb = new ConvertCarb();
convertCarb.CountryID = 150;
db.ConvertCarbs.Add(convertCarb);
db.SaveChanges();

以下是领域模型中的类:

public partial class ConvertCarb

    public int ConvertCarbID  get; set; 
    public Nullable<int> CountryID  get; set; 
    public virtual Country Country  get; set; 


public partial class Country

    public Country()
    
        this.ConvertCarbs = new List<ConvertCarb>();
        this.Offices = new List<Office>();
    

    public int CountryID  get; set; 
    public string CountryName  get; set; 
    public virtual ICollection<ConvertCarb> ConvertCarbs  get; set; 


public partial class StateProvince

    public StateProvince()
    
        this.Offices = new List<Office>();
    

    public int StateProvID  get; set; 
    public string StateProvAbbr  get; set; 
    public virtual ConvertCarb ConvertCarb  get; set; 
    public virtual ICollection<Office> Offices  get; set; 

这个插入应该没有问题,因为 ConvertCarbID 是一个标识列,我已经通过直接在数据库上运行 tsql 插入来验证这一点。

这是数据库中表的创建代码:

/****** Object:  Table [dbo].[ConvertCarb]    Script Date: 04/11/2014 03:04:24 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[ConvertCarb](
    [ConvertCarbID] [int] IDENTITY(1,1) NOT NULL,
    [CountryID] [int] NULL,
    [StateProvID] [int] NULL,
    [KWH_FT2] [float] NULL,
    [G_KWH] [decimal](18, 4) NULL,
    [NatGas_GJ_M2] [float] NULL,
    [FuelOil_GJ_M2] [float] NULL,
 CONSTRAINT [PK_ConvertCarb] PRIMARY KEY CLUSTERED 
(
    [ConvertCarbID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[ConvertCarb]  WITH NOCHECK ADD  CONSTRAINT [FK_ConvertCarb_Countries] FOREIGN KEY([CountryID])
REFERENCES [dbo].[Countries] ([CountryID])
GO

ALTER TABLE [dbo].[ConvertCarb] NOCHECK CONSTRAINT [FK_ConvertCarb_Countries]
GO

ALTER TABLE [dbo].[ConvertCarb]  WITH NOCHECK ADD  CONSTRAINT [FK_ConvertCarb_StateProvinces] FOREIGN KEY([ConvertCarbID])
REFERENCES [dbo].[StateProvinces] ([StateProvID])
GO

ALTER TABLE [dbo].[ConvertCarb] NOCHECK CONSTRAINT [FK_ConvertCarb_StateProvinces]
GO


/****** Object:  Table [dbo].[Countries]    Script Date: 04/11/2014 03:04:12 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Countries](
    [CountryID] [int] IDENTITY(1,1) NOT NULL,
    [CountryName] [varchar](255) NULL,
 CONSTRAINT [PK_Countries] PRIMARY KEY CLUSTERED 
(
    [CountryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO




/****** Object:  Table [dbo].[StateProvinces]    Script Date: 04/11/2014 03:05:23 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[StateProvinces](
    [StateProvID] [int] IDENTITY(1,1) NOT NULL,
    [StateProvAbbr] [varchar](2) NULL,
 CONSTRAINT [PK_StateProvinces] PRIMARY KEY CLUSTERED 
(
    [StateProvID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

以下是 EF 工具生成的映射类:

public class ConvertCarbMap : EntityTypeConfiguration<ConvertCarb>

    public ConvertCarbMap()
    
        // Primary Key
        this.HasKey(t => t.ConvertCarbID);

        // Properties
        // Table & Column Mappings
        this.ToTable("ConvertCarb");
        this.Property(t => t.ConvertCarbID).HasColumnName("ConvertCarbID");
        this.Property(t => t.CountryID).HasColumnName("CountryID");
        this.Property(t => t.StateProvID).HasColumnName("StateProvID");
        this.Property(t => t.KWH_FT2).HasColumnName("KWH_FT2");
        this.Property(t => t.G_KWH).HasColumnName("G_KWH");
        this.Property(t => t.NatGas_GJ_M2).HasColumnName("NatGas_GJ_M2");
        this.Property(t => t.FuelOil_GJ_M2).HasColumnName("FuelOil_GJ_M2");

        // Relationships
        this.HasOptional(t => t.Country)
            .WithMany(t => t.ConvertCarbs)
            .HasForeignKey(d => d.CountryID);
        this.HasRequired(t => t.StateProvince)
            .WithOptional(t => t.ConvertCarb);

    






public class CountryMap : EntityTypeConfiguration<Country>

    public CountryMap()
    
        // Primary Key
        this.HasKey(t => t.CountryID);

        // Properties
        this.Property(t => t.CountryName)
            .HasMaxLength(255);

        // Table & Column Mappings
        this.ToTable("Countries");
        this.Property(t => t.CountryID).HasColumnName("CountryID");
        this.Property(t => t.CountryName).HasColumnName("CountryName");
    



public class StateProvinceMap : EntityTypeConfiguration<StateProvince>

    public StateProvinceMap()
    
        // Primary Key
        this.HasKey(t => t.StateProvID);

        // Properties
        this.Property(t => t.StateProvAbbr)
            .HasMaxLength(2);

        // Table & Column Mappings
        this.ToTable("StateProvinces");
        this.Property(t => t.StateProvID).HasColumnName("StateProvID");
        this.Property(t => t.StateProvAbbr).HasColumnName("StateProvAbbr");
    

【问题讨论】:

没有使用实体框架我会说public int ConvertCarbID get; set; 是默认0 而不是null。你也试过nullable 当您查看 .edmx 模型中 ConvertCarbId 字段的属性时,它是否将 StoreGenerated 属性设置为 Identity 感谢您的评论。 ConvertCarbID 是主键。不能为空。 @paul 感谢您的评论。没有 .edmx 模型。我对 SQL Server 数据库进行了逆向工程。 @MarkRotteveel - 这不是该帖子的副本。我使用的是实体框架,而不是 T-SQL。 【参考方案1】:

这个关系映射...

this.HasRequired(t => t.StateProvince)
    .WithOptional(t => t.ConvertCarb);

...表示StateProvince 是主键,ConvertCarb 是共享主键一对一关系中的依赖项。在这种情况下,EF 假定只有主体可以具有标识主键,而依赖 ConvertCarb 不能(因为依赖必须始终具有与主体相同的 PK 值)。基本上这种关系会禁用ConvertCarb 实体的身份约定。结果,EF 将 ConvertCarb 实体的 PK 值(无论是手动提供还是默认值)发送到数据库(ConvertCarbID 列是 INSERT 语句的一部分),这会引发数据库异常,因为 ConvertCarbID列被标记为身份。

但是我不知道为什么 EF 会从数据库中获取这种一对一的关系,因为我在您的数据库脚本中没有看到对 StateProvince 的 FK 约束。或者该约束是否稍后添加到数据库中?

【讨论】:

感谢您的回复。我实际上把那个代码漏掉了。我试图只发布相关代码,但事实证明这是最相关的代码。我现在将其添加到原始帖子中。 外键关系被错误地映射到 ConvertCarbID 而不是 StateProvID。 这种有见地的答案让 SO 享有盛誉【参考方案2】:
public class ConvertCarbMap : EntityTypeConfiguration<ConvertCarb>

public ConvertCarbMap()

    // Primary Key
    this.HasKey(t => t.ConvertCarbID);

    // Properties
    this.HasKey(t => t.ConvertCarbID)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

    // Table & Column Mappings
    this.ToTable("ConvertCarb");
    this.Property(t => t.ConvertCarbID).HasColumnName("ConvertCarbID");
    this.Property(t => t.CountryID).HasColumnName("CountryID");
    this.Property(t => t.StateProvID).HasColumnName("StateProvID");
    this.Property(t => t.KWH_FT2).HasColumnName("KWH_FT2");
    this.Property(t => t.G_KWH).HasColumnName("G_KWH");
    this.Property(t => t.NatGas_GJ_M2).HasColumnName("NatGas_GJ_M2");
    this.Property(t => t.FuelOil_GJ_M2).HasColumnName("FuelOil_GJ_M2");

    // Relationships
    this.HasOptional(t => t.Country)
        .WithMany(t => t.ConvertCarbs)
        .HasForeignKey(d => d.CountryID);
    this.HasRequired(t => t.StateProvince)
        .WithOptional(t => t.ConvertCarb);



在 HasDatabaseGeneratedOption 中使用 DatabaseGeneratedOption.Identity。

【讨论】:

以上是关于实体框架抛出无法在表中插入标识列的显式值...当 IDENTITY_INSERT 设置为 OFF 错误的主要内容,如果未能解决你的问题,请参考以下文章

无法首先在表 ef6 db 中插入标识列的显式值

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

使用 C# 出现错误“无法在表中插入标识列的显式值”

当 IDENTITY_INSERT 设置为 OFF 时,无法在表“tbl Fingerprint”中插入标识列的显式值 [重复]

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

当 IDENTITY_INSERT 设置为 OFF 时,SQL 无法在表“表”中插入标识列的显式值 [重复]