LINQ Вставка в базу данных привела к дублированию - PullRequest
1 голос
/ 14 октября 2010

У меня есть запрос linq, выполняющийся в веб-службе WCF, который ищет совпадение, и если он не найден, он создает его.

мой код выглядит как

   //ReadCommitted transaction
   using (var ts = CreateTransactionScope(TransactionScopeOption.RequiresNew))
   {
    Contract contract = db.Contracts.SingleOrDefault(x => x.txtBlah == str);
    if (contract == null)
    {
      contract = new Contract();
      contract.txtBlah = str;
      db.Contracts.InsertOnSubmit(contract);
      db.SubmitChanges();
    }
    ...
    db.SubmitChanges();
   }

Проблема в том, что я получаю дубликаты. Я думал, что транзакция заблокировала бы базу данных, чтобы гарантировать, что дубликаты не будут найдены (и предоставили возможность отката). Как я могу убедиться в отсутствии дубликатов?

1 Ответ

0 голосов
/ 14 октября 2010

В транзакции ReadCommited данные могут быть изменены до конца транзакции. Но вы можете использовать Serializable транзакцию, которая будет выполнять блокировку таблицы.

db.Connection.Open();
using (db.Transaction = db.Connection.BeginTransaction(IsolationLevel.Serializable))
{
//your code here
db.Transaction.Commit();
}

Хорошо, если вы не хотите использовать Serializable trans, вы должны написать sproc для атомарной вставки, логика должна выглядеть следующим образом: SQL в коде:

db.ExecuteCommand("INSERT INTO Contract (txtBlah) SELECT {0} WHERE NOT EXISTS (SELECT 1 FROM Contract WITH (TABLOCK) WHERE txtBlah={0})", str);

обратите внимание, это также заблокирует всю таблицу во время вставки.

Подробнее о том, как создать звезду без условия гонки, можно узнать по адресу http://weblogs.sqlteam.com/dang/archive/2007/10/28/Conditional-INSERTUPDATE-Race-Condition.aspx.

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