2015-09-05 68 views
6

我需要在一個事務中來更新我的數據庫了幾桌,我讀了使用DbContext.SaveChanges應該是這樣做的方式。實體框架的DbContext和線程安全

不過,我也讀了,因爲它隨時間增長,因爲裝載更多的實體DbContext的生存時間應該越短越好。

我也讀,爲了讓線程安全的,每一個動作都應該有自己DbContext

對於每個我想更改的表,我是否應該有一個DbContext,並且每個DbContext上都要撥打SaveChanges?最後的SaveChanges調用是否會覆蓋之前調用的更改?

這樣做的最佳方法是什麼? (我需要這個網站)

+0

如果你想要做的這一切在一個單一的交易接單的DbContext是好的。不必擔心線程安全問題,因爲您需要按順序執行所有操作。 – DavidG

+0

@DavidG:但是如果2個用戶同時嘗試使用相同的DbContext?它不會造成競爭狀態嗎? – Idov

+0

你絕不應該讓這種事發生。 DbContext並不意味着被這樣使用,如果你嘗試,會做一些非常奇怪的事情! – DavidG

回答

1

簡單的方法是,讓每個請求的一個的DbContext,ASP.NET MVC做了所有線程安全的,在ASP.NET MVC中每個控制器實例被隔離爲每個請求,你不不得不擔心競賽狀況。只要你不創建線程,只需要使用單個DbContext在action方法中進行數據轉換,就不會有任何問題。

基本上DbContext什麼都不做,它只是將SQL查詢排隊到目標數據庫,它是處理多線程,競爭條件的數據庫。爲了保護您的數據,你應該使用交易,並在您的數據庫中添加驗證,以確保它們被正確地保存

public abstract class DbContextController : Controller{ 

    public AppDbContext DB { get; private set;} 

    public DbContextController(){ 
     DB = new AppDbContext(); 
    } 

    protected override void OnDisposing(bool disposing){ 
     DB.Dispose(); 
    } 

} 

如果從DbContextController繼承任何類,並使用DB整個控制器的生活,你不會有任何問題。

public ActionResult ProcessProducts(){ 
    foreach(var p in DB.Products){ 
     p.Processed = true; 
     foreach(var order in p.Orders){ 
      order.Processed = true; 
     } 
    } 
    DB.SaveChanges(); 
} 

但是,如果你在下面的示例中使用任何線程一樣,

public ActionResult ProcessProducts(){ 
    Parallel.ForEach(DB.Products, p=>{ 
     p.Processed = true; 
     // this fails, as p.Orders query is fired 
     // from same DbContext in multiple threads 
     foreach(var order in p.Orders){ 
      order.Processed = true; 
     } 
    }); 
    DB.SaveChanges(); 
} 
1

Entity Framework is not thread-safeAn MVC controller is instantiated per request。因此,如果每個請求使用一個DbContext,只要您不在控制器操作中手動生成線程(您不應該這樣做),就是安全的。

現在,如果您的應用程序中有併發,就像預訂系統中多個用戶訪問可能用完的相同稀缺資源(如票據)一樣,您必須自己實現邏輯。無論如何,線程安全無論如何都會幫助你。

這就是爲什麼你被要求在評論代碼,因爲一般解釋線程安全是太廣泛,可能並不適用於您的情況。