TSQL вставка данных, связанных внешним ключом - PullRequest
0 голосов
/ 27 марта 2012

Допустим, у меня есть две таблицы

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».

Разве транзакция не должна знать, что я вставляю внешний ключ на основе вставки, которую я только что сделалав контексте текущей транзакции?Я далеко?

Как ты это сделал?

Ответы [ 3 ]

1 голос
/ 27 марта 2012

Потому что 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
0 голосов
/ 28 марта 2012

Я сбросил внешний ключ и воссоздал его, и он начал работать.

0 голосов
/ 27 марта 2012

Вот 2 возможных решения для вас, если я понял вашу проблему:

  1. Вы можете установить уровень изоляции транзакции и использовать READ UNCOMMITTED / NOLOCK, чтобы выполнить грязное чтение ранеевставлена ​​запись в транзакции (см. этот пост для более Зачем использовать уровень изоляции READ UNCOMMITTED? )

  2. Вы можете просто создать Guid в коде и вручную вставить в2 таблицы в качестве параметра SqlCommand вместо использования SCOPE_IDENTITY() после первой вставки.(Мой предпочтительный вариант)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...