簡單的方法是,讓每個請求的一個的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();
}
如果你想要做的這一切在一個單一的交易接單的DbContext是好的。不必擔心線程安全問題,因爲您需要按順序執行所有操作。 – DavidG
@DavidG:但是如果2個用戶同時嘗試使用相同的DbContext?它不會造成競爭狀態嗎? – Idov
你絕不應該讓這種事發生。 DbContext並不意味着被這樣使用,如果你嘗試,會做一些非常奇怪的事情! – DavidG