2012-03-26 126 views
0

比方说,我有两个表外键关联TSQL插入数据

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语句冲突与外键约束 “FK_RDB_DataInstances_RDB_DataEntities”。冲突发生在 数据库'NMSS_CMS',表'dbo.RDB_DataEntities', 'DataEntityId'列中。

事务不应该知道我插入的外键基于插入我只是在当前事务上下文中做的?我离开吗?

你如何做到这一点?

+0

它没有发生在你的第一个'INSERT'上吗?也就是说,你没有设置FK的方式是错误的... – 2012-03-27 03:41:49

回答

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 
+2

另一种解决方案:使用输出子句。保存查询。 – 2012-03-26 20:53:41

+0

SCOPE_IDENTITY()明确地适用于两种方式。我调试过,以确保我的var id肯定有一个整数值。 – Micah 2012-03-26 20:55:12

+0

如果你正在获得正确的价值,那么我同意它应该起作用。你正在尝试做的T-SQL版本是合乎逻辑的。 – mgnoonan 2012-03-26 21:02:19

0

下面是你2个可能的解决方案,如果我理解你的问题:

  1. 您可以设置事务隔离级别,并使用READ UNCOMMITTED/NOLOCK对先前插入执行脏读记录在交易中(看到这篇文章的更多Why use a READ UNCOMMITTED isolation level?

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

0

我放弃了外键并重新创建它并开始工作。