當我們需要做的在我們的應用程序的數據庫訪問,我們採用以下模式:的SqlConnection和避免推廣MSDTC
- 用於查詢,我們有一個靜態工廠類的方法
CreateOpenConnection
這確實不外乎new SqlConnection(myConnectionString)
並在其上調用Open()
。在執行查詢之前調用此方法,並在查詢返回後處理連接。 - 對於插入/更新/刪除我們使用其中的變化是成批並通過調用提交到數據庫
work.Commit()
像這樣工作模式的單位:
work.Commit:
using (var tranScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using (var conn = DapperFactory.CreateOpenConnection())
{
var count = _changeTracker.CommitChanges(conn);
tranScope.Complete();
return count;
}
}
這似乎很適合作爲web服務的一部分的一般用法,但是當我嘗試與Rebus結合使用時,目前給我MSDTC的麻煩。
從我所知道的情況來看,Rebus(當它處理隊列中的消息時)會創建一個新的TransactionScope
,以便在消息處理失敗的情況下可以回滾。現在,這本身迄今爲止工作得很好。我可以打開一個滷麪消息處理程序中一個新的SqlConnection
沒有任何問題(然而,用我們傳統的實體框架查詢和相同滷麪TransactionScope
不起作用裏面手動SqlConnections,但我不認爲一個問題現在) 。不過,昨天我提出以下問題:
Serial processing of a certain message type in Rebus
這個問題的答案似乎是使用滷麪的傳奇特性。我試圖實現這一點,並配置它,以便Rebus傳奇獲取持久化到一個新的SQL Server數據庫(具有不同的連接字符串)。據推測,使用SQL Server的持久性打開了自己的SqlConnection
,因爲任何時候,我現在嘗試創建一個SqlConnection
,我得到以下異常:對於分佈式事務管理器
網絡訪問(MSDTC)已被禁用。請使用組件服務管理工具在MSDTC的安全配置中啓用DTC以進行網絡訪問。
啓用MSDTC是我會非常,非常希望避免這樣做,關於配置和性能開銷。我可能是錯的,但它似乎也不是必要的。
我估計這裏發生的事情是,Rebus創建了一個環境TransactionScope
並且它創建了該範圍的登記信息。當我嘗試創建我自己的SqlConnection
時,它也嘗試登錄到該環境範圍,並且由於涉及多個連接,它將被提升爲MSDTC,從而失敗。
我對如何解決此問題的想法,但我不知道它是做正確的事。我會做的是:
- 添加
Enlist=false
到我的應用程序的連接字符串,以便它永遠不會徵到環境事務。 - 修改
Commit
方法,以便它不會創建一個新的TransactionScope
(我的連接不會再訂閱,因爲我只是告訴它不應該),但它使用conn.BeginTransaction
。
像這樣:
var transaction = conn.BeginTransaction();
try
{
var count = _changeTracker.CommitChanges(conn);
transaction.Commit();
return count;
}
catch
{
transaction.Rollback();
throw;
}
finally
{
transaction.Dispose();
}
我只是不知道這是正確的做法,什麼可能的缺點。
任何提示?
UPDATE:要澄清,這不是一個已經給我的問題了work.Commit()
,我敢肯定它會工作,但我從來沒有到那裏,因爲我查詢就是失敗。
什麼失敗的例子:一個SqlConnection
由滷麪打開
public int? GetWarehouseID(int appID)
{
var query = @"
select top 1 ID from OrganizationUnits o
where TypeID & 16 = 16 /* warehouse */";
using (var conn = _dapper.OpenConnection())
{
var id = conn.Query<int?>(query).FirstOrDefault();
return id;
}
}
這被當TransactionScope
已經滷麪創建調用,以及之後。打開我的SqlConnection
,它試圖登記和崩潰
如果您使用「Enlist = false」,肯定會使您的'TransactionScope'毫無意義?因爲連接*不會在其中* –
同樣,你的'BeginTransaction'代碼*沒有使用事務* - 需要在命令中明確指定ADO.NET事務,所以你需要通過'交易'到'CommitChanges',當然? –
你能說清楚你正在使用哪個版本的sql server嗎? –