假设我有两张桌子
RDB_DataEntities
DataEntityId
Name
Created
Modified
...
RDB_DataInstances
DataInstanceId
DataEntityId
所以RDB_DataInstances
通过RDB_DataEntities
列上的外键加入DataEntityId
。
假设我想在同一个事务中的两个表中插入数据。我的代码如下:
using (var con = new SqlConnection("data source=speedy;initial catalog=mydb;user id=myuser;password=mypass"))
{
con.Open();
using (var tran = con.BeginTransaction())
{
SqlCommand i1 = new SqlCommand("insert into RDB_DataEntities (Name,IsSchema,Created,Modified,RequireCaptcha,UniqueByEmail,UniqueByMac) values ('hi',0,GetDate(),GetDate(),0,0,0)", con, tran);
i1.ExecuteNonQuery();
SqlCommand i2 = new SqlCommand("select SCOPE_IDENTITY() as newid", con, tran);
var id = int.Parse(i2.ExecuteScalar().ToString());
SqlCommand i3 = new SqlCommand("insert into RDB_DataInstances (DataEntityId) values (" + id + ")", con, tran);
i3.ExecuteScalar();
tran.Commit();
}
}
为什么会抛出外键错误
INSERT语句与FOREIGN KEY约束冲突 'FK_RDB_DataInstances_RDB_DataEntities'。冲突发生在 数据库'NMSS_CMS',表'dbo.RDB_DataEntities',列 'DataEntityId'。
事务是否应该知道我是否根据我刚才在当前事务上下文中执行的插入插入外键?我离开了吗?
你是如何实现这一目标的?
答案 0 :(得分:1)
因为当您使用两个不同的命令上下文时,SCOPE_IDENTITY()
将不起作用(根据定义,它是一个单独的范围)。您可以将第二个查询附加到第一个查询,然后运行ExecuteScalar()
,如下所示:
SqlCommand i1 = new SqlCommand("insert into RDB_DataEntities (Name,IsSchema,Created,Modified,RequireCaptcha,UniqueByEmail,UniqueByMac) values ('hi',0,GetDate(),GetDate(),0,0,0);select SCOPE_IDENTITY() as newid;",con,tran);
var id=int.Parse(i1.ExecuteScalar().ToString());
编辑:只是想把正在发生的事情的T-SQL版本放在一起。
DECLARE @newid int
BEGIN TRANSACTION
insert into RDB_DataEntities
(Name,IsSchema,Created,Modified,RequireCaptcha,UniqueByEmail,UniqueByMac)
values
('hi',0,GetDate(),GetDate(),0,0,0)
SELECT @newid = SCOPE_IDENTITY()
insert into RDB_DataInstances
(DataEntityId)
values
(@newid)
COMMIT TRANSACTION
答案 1 :(得分:0)
如果我理解了你的问题,这里有2个可能的解决方案:
您可以设置事务隔离级别并使用READ UNCOMMITTED / NOLOCK对事务中先前插入的记录执行脏读(请参阅此帖子了解更多Why use a READ UNCOMMITTED isolation level?)
您可以在代码中创建Guid并手动插入2个表中作为SqlCommand参数,而不是在第一次插入后使用SCOPE_IDENTITY()
。 (我的首选)
答案 2 :(得分:0)
我删除了外键并重新创建它并开始工作。