2010-10-13 77 views
1

我有一個linq查詢運行在WCF Web服務中查找匹配,如果找不到,那麼它創建一個。LINQ插入到數據庫導致重複

我的代碼看起來像

//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(); 
    } 

的問題是,我得到重複。我認爲這個事務會鎖定數據庫以確保沒有發現重複(並提供回滾功能)。我怎樣才能確保沒有重複?

回答

0

在ReadCommited事務中,可以在事務結束之前更改數據。但是你可以使用Serializable事務來處理表鎖。

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

好吧,如果你不想使用序列化的移植,那麼你應該寫原子插入一個存儲過程,邏輯應該是這樣的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

+1

這將阻止該地區周圍的每一個電話..我只能鎖定插入部分?也就是在readcommitted事務內的塊序列化事務? – BabelFish 2010-10-13 21:54:02

+0

aka我可以得到BeginReadCommitTran {DoSomeFunctions; BeginSerializableTran {Insert;承諾; } DoMoreFunctions;承諾; }如果這是有道理的 – BabelFish 2010-10-13 21:57:20

+0

只把select和insert插入一個可串行化的tran或者爲它寫一個sproc。 – jomi 2010-10-13 21:57:42

相關問題