栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Cannot insert explicit value for identity column in table ‘xxx‘ when IDENTITY

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Cannot insert explicit value for identity column in table ‘xxx‘ when IDENTITY

Cannot insert explicit value for identity column in table ‘T_ADDRESS’ when IDENTITY_INSERT is set to OFF.

.Net 产生该错误的原因:

1、SQL Server层面(网上比较多的解释)

1.1 不能向 SQL Server 自增字段插入值

详细解释为:当我们的主键设置为自增,并且我们在insert数据时给主键赋值了,这个时候是不允许的。
如下面的 AddressKey 字段中的 IDENTITY(1,1)

CREATE TABLE [dbo].[T_ADDRESS](
	[AddressKey] [int] IDENTITY(1,1) NOT NULL,     --IDENTITY(1,1):起始值为1,自增值为1;
 CONSTRAINT [PK_T_ADDRESS] PRIMARY KEY CLUSTERED 
(
	[AddressKey] 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

1.2 如果你有特殊情况,需要插入特定的值,那么请参考如下

set identity_insert T_ADDRESS on

insert into T_ADDRESS (AddressKey) values(5)

set identity_insert T_ADDRESS off    --注意的是,自增字段插入值后,要及时把 identity_insert 设置为 off

2、代码、框架层面导致( .Net );

无论你是Web Service(API)还是Web Client(客户端),基于二者的后台框架技术,总结如下:

无论DAL层是基于依赖注入还是基于DBContext上下文的,DB Model之间都不可以通过继承的方式进行定义
(例如:历史表和原表不可以通过继承的方式进行定义,否则在insert Into 历史表时,插入的会是原表,也因此会产生上面的错误信息;)

举例:Table_A有一个主键字段KeyId;Table_B类也有一个主键字段KeyId + DeleteBy字段;(基于DBContext的举例)

需求:删除Table_A表数据,并将数据备份到Table_B中;

public class Table_A
{
	private int KeyId { get; set; } //主键 [int] IDENTITY(1,1) NOT NULL  //原表有自增
}

//public class Table_B
//{
	//private int KeyId { get; set; } //主键 [int] NOT NULL   //历史表无自增
	//private string DeleteBy { get; set; }
//}

public class Table_B : Table_A
{
	private string DeleteBy { get; set; }
}


public static void main()
{
	try
	{
		//public virtual DbSet Table_A { get; set; }
		//public virtual DbSet Table_B { get; set; }
		
		Table_A tableA = db.Table_A.Where(c => c.KeyId = 1).FirstOrDefault();//基于DBContext
		Table_B tableB = new Table_B()
		{
		    KeyId= tableA.KeyId,
			DeleteBy = "Myself",
		}
		
		db.Table_A.Remove(tableA);
		db.Table_B.Insert(tableB);
		db.SaveChanges();// 在这里会报异常:
	}
	catch (Exception ex)
	{
		//Cannot insert explicit value for identity column in table 'Table_A' when IDENTITY_INSERT is set to OFF.
	}
}

通过调试发现,代码运行到db.Table_B.Insert(tableB)时,SQLServer中实际是在向Table_A中插入tableB对象;

结论:此问题与依赖注入、EF、EF Core无关;在C#中用户自定义Class属于引用类型,实际数据存储在“堆”中;当历史表继承原表,那么在对历史表进行依赖注入或者在对历史表进行 DbSet<> 时,实际上是对原表进行的操作,而非历史表;

知识点:EF仍然是对ADO.Net的封装;
因此:在DAL层,无论是否是ADO.Net还是ASP.Net,一个Entity必须遵循一 一对应DB中的Table;如果有继承关系,那么父类必须是 abstract 的;

-------------------------欢迎讨论和指教-------------------------

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005895.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号