2012-10-08 74 views
3

我已經創建了幾個自定義活動在我的數據庫是更新表(在這種情況下的SQL Server Compact),使用實體框架4波蘇斯幾個自定義活動。WF4的TransactionScope含EF4數據庫更新

如果我把這些多於一個WF4 TransactionScope活動中,我遇到了問題:EF部署的第一個活動後,DB連接已經完成,並在接下來的DB活動試圖做一個數據庫更新一新的連接建立起來了。此時出現異常。

System.Activities.WorkflowApplicationAbortedException : The workflow has been aborted. 
----> System.Data.EntityException : The underlying provider failed on Open. 
----> System.InvalidOperationException : The connection object can not be enlisted in transaction scope. 

我是否必須在整個事務處理範圍內保持EF連接處於打開狀態?我怎樣才能做到這一點?爲此創建一個明確的自定義活動,還是有標準的方式?

我目前的解決方法是這樣的:我創建了一個新的代碼活動,創建我們的ObjectContext並明確調用dbContext.Connection.Open()。它返回ObjectContext,然後將其保存在工作流變量中。那一個被傳遞給所有與數據庫相關的活動,作爲Injegument <>。在我的數據庫活動中,如果它傳入,我使用這個ObjectContext,否則我創建一個新的。

這並不工作,但我不滿意這個解決方案:它需要爲每一個數據庫相關活動的新InArgument。在工作流設計器中,我必須在事務範圍內插入特殊的OpenDatabaseConnection活動,然後確保將正確的變量傳遞到所有數據庫活動中。這似乎是非常不雅和容易出錯的,特別是如果其他團隊成員必須使用這些數據庫活動。

什麼會是一個更好的方式來處理呢?

回答

1

的問題是,當您打開在同一事務範圍的第二連接,試圖促進事務分佈式事務(即使沒有什麼分佈有關,因爲你連接到同一個數據庫)。 SQL Server CE不支持這種情況。

我會做的是創建一個打開(或關閉)的連接,並使其可用於兒童活動定製的「容器」的活動。這仍然不是最佳的,但至少你不再需要通過InArgument。會得到以下活動樹:

TransactionScope 
    InitializeConnection 
     Sequence 
      CustomDataActivity1 
      CustomDataActivity2 
      CustomDataActivity3 

InitializeConnection是使用NativeActivityContext.Properties暴露的連接(或ObjectContext)兒童活動NativeActivity

確保你實施適當的錯誤處理,以確保您收在任何時候都連接。

注意:分佈式事務由完整的SQL Server只能通過Windows服務名爲MSDTC(Microsoft分佈式事務處理協調器)的支持。你可以在你的「本地服務」中找到這個。由於SQL Server CE是一個應該能夠完全獨立運行的數據庫,因此它對MSDTC沒有依賴性是有意義的。因此它不支持分佈式事務。

+0

謝謝,這聽起來很合理。我想我可以將TransactionScope和新的InitializeConnection結合成一個本地的「DatabaseTransactionScope」,這樣就不會在設計器表面產生額外的混亂。然而,我想我需要爲此創建一個自定義設計器,以便將序列拖放到新活動中。這對於這個小功能來說有很大的開銷:( – Achim

+0

將兩者結合起來是可能的,我同意這是很多工作。當然,不確定它是否值得在你的情況下遇到麻煩,這取決於你可以多久重用一次以及如何重用你認爲所有的InArgument都是一個問題,你也可以從擁有這個InArgument的公共基類中擴展你所有的數據活動,而不是像其他解決方案那樣乾淨,但是更容易實現.. –

+0

做你有解決你的解決方案的任何代碼示例嗎?'CustomDataActivityXXX'必須是_NativeActivity_才能訪問由'InitializeConnection'活動設置的屬性?目前它們都是從_AsyncCodeActivity_派生的。說實話,我沒有使用NativeActivity到目前爲止,只有AsyncCodeActivity和CodeActivity – Achim