TSQL插入由外键链接的数据

本文关键字:链接 数据 插入 TSQL | 更新日期: 2023-09-27 18:29:15

假设我有两个表

RDB_DataEntities

DataEntityId
Name
Created
Modified
...

RDB_DataInstances

DataInstanceId
DataEntityId

因此,RDB_DataInstances通过它们的DataEntityId列上的外键与RDB_DataEntities连接。

假设我想将数据插入到同一事务中的两个表中。我的代码如下:

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_Data_Entities",列"DataEntityId"。

事务难道不应该知道我正在根据我刚刚在当前事务上下文中进行的插入来插入外键吗?我离这儿很远吗?

你是如何做到这一点的?

TSQL插入由外键链接的数据

因为当您使用两个不同的命令上下文时,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. 您可以设置事务隔离级别,并使用READ UNCOMITTED/NOLOCK对事务中先前插入的记录执行脏读取(请参阅本文了解更多信息为什么使用READ uncOMITTED隔离级别?)

  2. 您可以在代码中创建Guid,并将其作为SqlCommand参数手动插入到两个表中,而不是在第一次插入后使用SCOPE_IDENTITY()。(我的首选)

我删除了外键并重新创建了它,它就开始工作了。