2

我使用AutoFac在我的Web應用程序中注入一個具體的數據上下文。如果頁面上沒有例外,我希望在請求結束時執行數據庫上下文的SaveChanges()方法。否則,我只是想正常處理上下文。使用AutoFac OnRelease保存DbContext更改?

我注意到AutoFac有一個OnRelease方法。該方法的智能感知狀態爲:

運行提供的操作,而不是在實例不再需要時處置實例。

因此,我想在做這樣的事情的:

builder.RegisterType<MyContext>().As<IDbContext>().InstancePerHttpRequest() 
    .OnRelease(x => { 
     if (HttpContext.Current != null && HttpContext.Current.Error == null) 
      x.SaveChanges(); 
     if (x != null) 
     { 
      x.Dispose(); 
      x = null; 
     } 
    }); 

這是一個合適的位置提交的數據環境的變化?即使發生異常,它是否可以保證在每個請求上運行?

回答

2

一般來說,當您在請求結束時保存更改時,我不喜歡這種方法,因爲您在此處失去了靈活性。好的做法是保存業務交易結束時的變更。想象一下這樣的示例代碼:

public ActionResult CreateAccount(CreateAccountModel createAccountModel) 
{ 
    // Your business transaction start here from validating and processing input data 
    var account = CreateAccountFrom(createAccountModel); 
    _yourContext.Add(account); 
    // Your business transaction ends here 
    // This is the good place to commit your transaction 
    _yourContext.SaveChanges(); 

    // You can have another business transaction here 

    // the following is not important code to log the event 
    // which could break the business transaction if it would be within one 
    // you can wrap it in try-catch for example 
    _yourContext.Add(new Event(){ Type = AccountCreated }); 
    _yourContext.SaveChanges(); 

    // code to retrieve date for the view 
    var viewModel = GetViewModel(); 
    return View(viewModel); 
} 


現在關於你的代碼,總之,這是一個不好的地方保存更改。首先你違反單一責任原則,OnRelease應該在沒有IDisposable的類上清理資源,但不要做額外的邏輯。把業務邏輯放在那裏是不好的,因爲你可以做到這一點。第二件事,如果你在x.SaveChanges()上得到一個異常,你的上下文將不會被處置。最好不要混淆業務邏輯和對象生命週期邏輯。

+0

Alexandr,謝謝你的回答。在需要時,我可以靈活地在代碼中調用SaveChanges()。另外,我不能在try/catch/finally塊中包裝'SaveChanges()',就像我在其他代碼中處理您對處置的擔心一樣嗎? – Sam

+1

@Sam「我需要時可以靈活地在代碼中調用SaveChanges()。」你爲什麼要結合這兩種方法?它導致錯誤。 「我無法將SaveChanges()包裝在try/catch/finally塊中」是的,它會工作,但...... :) –