2011-03-05 55 views
7

在使用MVC應用程序時管理實體框架上下文的最佳方式是什麼?EF上下文管理

我正在使用存儲庫/服務模式。

編輯

通過其中的一些問題細算:stackoverflow.com/users/587920/sam-striano,我更糊塗了,然後前。有人說每個存儲庫使用上下文,但是如果我想在一個控制器方法中使用多個存儲庫,

爲了遵循良好的分離設計,您如何在MVC應用程序中使用UnitOfWork,使其不依賴於EF?我希望能夠使用模擬環境對我的控制器,模型,服務等進行單元測試?

+0

此討論的許多倍。例如,我推薦你從上週的用戶提出的問題:http://stackoverflow.com/users/587920/sam-striano然後問你發現的具體問題。 – 2011-03-05 18:12:53

+0

@Lad - 請參閱我的編輯。 – Andrew 2011-03-05 18:28:08

+0

這是一個很好的帖子,顯示了EF Code First Repository Patter的代碼,其中包含一個工作單元。它使用Structuremap作爲IoC並具有所有內容的代碼示例。 http://stackoverflow.com/questions/4442828/entity-framework-4-ctp-4-ctp-5-generic-repository-pattern-and-unit-testable – Paul 2011-03-05 22:18:00

回答

6

使用依賴注入控制框架/反轉,如:

  1. Ninject
  2. Autofac
  3. StructureMap
  4. 統一

使用IoC容器,你可以告訴它如何管理單個數據上下文(最常見的是每個請求)。當您爲每個請求設置數據上下文時,容器會自動奇蹟般地爲每個請求提供需要數據上下文相同數據上下文的任何類。

這是關於設置Ninject的good article

你的代碼將最有可能最終看起來像,假設你使用一個通用存儲庫:

Ninject模塊:

public class NinjectRegistrationModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<MyDataContext>().ToSelf().InRequestScope(); 
     Bind(typeof(RepositoryImplementation<>)).ToSelf().InRequestScope(); 

    } 
} 

通用存儲庫:

public RepositoryImplementation<T> : IRepository<T> where T : class 
{ 
    MyDataContext _dataContext; 

    public RepositoryImplementation<T>(MyDataContext dataContext) 
    { 
     _dataContext = dataContext; 
    } 

    // bunch of methods that utilize _dataContext 
} 

服務類別:

public class MyServiceClass 
{ 
    IRepository<SomeEntity> _someEntityRepository; 

    public MyServiceClass(IRepository<SomeEntity> someEntityRepository) 
    { 
     _someEntityRepository = someEntityRepository; 
    } 

    // do stuff with _someEntityRepository = someEntityRepository; 
} 

控制器:

public class MyController 
{ 
    MyServiceClass _myServiceClass; 

    public MyController(MyServiceClass myServiceClass) 
    { 
     // Ninject will auto-magically give us a myServiceClass 
     // which will Ninject will inject a repository into MyServiceClass's constructor 
     _myServiceClass = myServiceClass; 
    } 

    public ActionResult MyAction() 
    { 
     // use _myServiceClass to do stuff 
     return View(); 
    } 
} 
+0

我喜歡直接投資,但您仍應該從存儲庫中實例化ObjectContext。例如,考慮由IoC容器配置爲單例的存儲庫的後果,並接收ObjectContext作爲構造函數參數。 – smartcaveman 2011-03-05 20:41:44

+0

偉大的職位,謝謝!但我有幾個問題。 1)在Ninject Bind示例中,我使用EF4,您從哪裏獲取Bind ()。ToSelf()。InRequestScope();)的上下文。 MVC應用程序不應該知道EF,對嗎? – Andrew 2011-03-05 23:28:54

+0

您是否嘗試將Ninject模塊放入您的服務層,並將其引用到您的ASP.NET MVC項目中? – Omar 2011-03-05 23:49:33

0

如果您的功能很簡單,那麼您應該在每個存儲庫中創建一個新的ObjectContext。實例化它們很便宜。

如果這樣會產生衝突,您可以按照評論中的建議使用工作單元模式。

我建議你在將ObjectContext或DataContext與DI容器集成時非常謹慎。許多人在默認情況下並未在其生命週期中使用適當的範圍。

+0

每個存儲庫有一個新的上下文是隻適用於簡單的場景。您通常會發現您想要在多個存儲庫之間共享上下文。這通常通過使用UnitOfWork模式來處理。 – 2011-03-05 18:14:32

+0

UnitOfWork模式的任何好例子? – Andrew 2011-03-05 18:22:03

+0

http://martinfowler.com/eaaCatalog/unitOfWork.html – smartcaveman 2011-03-05 18:26:59