12

我有一個使用IoC(Unity)的MVC 3網站,我的模型是用EF4和POCO生成的。我使用的是動作過濾器提交我的UnitOfWork:UnitOfWork in Action似乎是緩存

public class UseUnitOfWorkAttribute : ActionFilterAttribute, IActionFilter 
{ 
    private readonly IUnitOfWork _unitOfWork; 

    public UseUnitOfWorkAttribute() 
    { 
     _unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
    } 

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     _unitOfWork.Commit(); 
    } 

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    } 
} 

然而,即使Commit()似乎是被解僱,它在某種程度上似乎是緩存它認爲是「髒」。

例如,在我的控制器,下面會從一個服務類執行:

var user = _userRepository.Single(u => u.Id == 2); 
user.DateAdded = DateTime.Now; 

每當我做解決方案的一個新的構建和打這個控制器動作,改變實際提交。然而,對控制器的連續命中沒有任何作用。

在另一方面,如果我把一個的UnitOfWork在我的控制器並提交下列服務方法調用,它將按預期工作(我每次請求控制器動作):絕對

public AccountController() 
{ 
    _unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
} 

public ActionResult Test() 
{ 
    var user = _userRepository.Single(u => u.Id == 2); 
    user.DateAdded = DateTime.Now; 
    _unitOfWork.Commit(); 
} 

所以看起來像某種緩存正在進行,但我無法弄清楚什麼是緩存 - 單元工作室,ActionFilter,或存儲庫。

任何想法可能會發生什麼?如果沒有,我還有什麼想法可以解決問題?

在此先感謝。

回答

26

您正在初始化您的工作單元的動作過濾器的構造函數,這意味着它將在動作過濾器實例化時被注入。從ASP.NET MVC 3 release notes報價:

在ASP.NET MVC的早期版本中, 行動過濾器每 請求創建,除了在少數情況下。這種行爲從來沒有保證 的行爲,但僅僅是一個實施 細節和過濾器 的合同被認爲是無狀態的。在ASP.NET MVC 3中,積極地緩存更多的過濾器 。因此,任何不正確地存儲 實例狀態的自定義 操作篩選器可能會中斷。

+0

謝謝,這是令人興奮的發生了什麼事情。我試圖找到有關操作過濾器緩存的信息,但從未在我的搜索中遇到過這種情況。 – 2011-03-17 12:27:43

+0

好,@Darin! – neontapir 2011-03-17 13:37:21

+0

我希望我能投這個5倍。 Killer升級MVC 1/2應用程序時。 – Paul 2013-05-01 17:31:35

0

我會檢查存儲庫中的生命週期。這無疑是我們實施的罪魁禍首。

+0

我使用'TransientLifetimeManager()'在我的倉庫。我的ObjectContext和UnitOfWork都使用自定義的'PerExecutionContextLifetimeManager()',這基本上是每個請求的生命週期。我的倉庫是否也應該是'PerExecutionContextLifetimeManager()'? – 2011-03-17 06:02:53

+0

更新:我只是試過,只是爲了排除,並使用'PerExecutionContextLifetimeManager()'似乎也有相同的結果。我應該嘗試其他選擇嗎? – 2011-03-17 06:05:38

6

確保依賴容器在所有地方返回相同的實例和重寫過濾器,以避免狀態緩存:

public class UseUnitOfWorkAttribute : ActionFilterAttribute, IActionFilter 
{ 
    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
     unitOfWork.Commit(); 
    } 

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    } 
} 
+0

謝謝,這個解決方案的作品。 – 2011-03-17 12:28:16