[英]Two nested Entity Framework contexts, sharing a transaction
我有看起來像下面的示例的代碼。 由於需要通過SP完成一些數據庫偽造,並且其中包含一個保存更改,因此涉及到顯式事務。 (異常處理,回滾等。省略):
void OuterMethod(MyDatbase context)
{
using(var dbTrans = context.Database.BeginTransaction())
{
// some stuff, the save puts the data where the SP can see it
Stuff(context);
context.SaveChanges();
// now some SP stuff
context.Database.ExecuteSqlCommand(@"spFoo", params);
// more stuff
MoreStuff(context);
AlmostUnrelatedCode(context);
context.SaveChanges();
dbTrans.Commit();
}
}
現在,方法AlmostUnrelatedCode()
-僅與上述過程略相關-在99%的時間中需要一個不錯的,快速的,一次性的只讀上下文。 我有一家工廠,可以在需要時為我提供合適的服務。 從上面那個塊的中間被調用的時間的1%。
MyDatabase localReadOnlyContext;
void AlmostUnrelatedCode(MyDatabase context)
{
if ( context.Database.CurrentTransaction != null )
{
// Must use the context passed or everything deadlocks :(
localReadOnlyContext = context;
disposeContextLater = false;
}
else
{
// I just want to do this all the time
localReadOnlyContext = _contextFactory.CreateReadOptimized();
disposeContextLater = true;
}
// Do many, many things with my read-optimized context...
// The Dispose() on the class will check for disposeContextLater
}
我想做的是擺脫該事務檢查,實際上,如果我能幫助的話,根本不需要傳遞外部上下文。
我試過的
只是忽略外部事務中發生的事情,並一直使用我生成的上下文。 問題:僵局。
嘗試將最外層事務放入_contextFactory
創建的EF上下文中。 問題:EF上下文構造函數不允許您傳遞現有事務。 Database.CurrentTransaction
也沒有設置器。
將整個事務拉出到包裹所有內容的TransactionScope
中。 問題:方法OuterMethod
在上下文中傳遞,並且我無法控制調用者。
我無法嘗試的是:
AlmostUnrelatedCode()
需要到目前為止已寫入的數據。 我寧願不:
AlmostUnrelatedCode
內部使用外部上下文AlmostUnrelatedCode
。 AlmostUnrelatedCode
處理大量數據樹,並且上下文很快變得發胖和不快樂。 它很快就用廢話污染了上下文,我寧願在完成后就將其丟棄。 您可以通過將一個連接用於多個上下文來防止死鎖。
例
var efConnectionString = ConfigurationManager.ConnectionStrings["SomeEntities"].ConnectionString;
// note EntityConnection, not SqlConnection
using (var conn = new EntityConnection(efConnectionString)) {
// important to prevent escalation
await conn.OpenAsync();
using (var c1 = new SomeEntities(conn, contextOwnsConnection: false)) {
//Use some stored procedures etc.
count1 = await c1.SomeEntity1.CountAsync();
}
using (var c2 = new SomeEntities(conn, contextOwnsConnection: false)) {
//Use some stored procedures etc.
count2 = await c2.SomeEntity21.CountAsync();
}
}
在您的情況下,只需從上下文獲取連接並重用它
context.Database.Connection
您AlmostUnrelatedCode
像這樣將在AlmostUnrelatedCode
完成的事情分開:
void AlmostUnrelatedCode()
{
var context = _contextFactory.CreateReadOptimized();
AlmostUnrelatedCode(context);
context.Dispose();
}
void AlmostUnrelatedCode(MyDatabase context)
{
// Do many, many things with context...
}
現在,您可以從OuterMethod
調用AlmostUnrelatedCode(with param)
。 也許還有更多的東西需要分離。 考慮S OLID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.