EF上下文管理

7
什么是在使用MVC应用程序时管理Entity Framework上下文的最佳方法?
我正在使用存储库/服务模式。
编辑
查看一些这些问题:stackoverflow.com/users/587920/sam-striano后,我比以前更困惑了。有些人说每个存储库使用上下文,但如果我想在一个控制器方法中使用多个存储库怎么办?
为了遵循良好的分离设计,如何在不使其依赖于EF的情况下在MVC应用程序中使用UnitOfWork?我希望能够使用模拟上下文来对控制器、模型、服务等进行单元测试。

这个问题已经讨论了很多次。例如,我建议你查看上周该用户的问题:http://stackoverflow.com/users/587920/sam-striano 然后请提出你发现的具体问题。 - Ladislav Mrnka
这是一篇很好的文章,展示了EF Code First Repository Pattern with a Unit of Work的代码。它使用Structuremap作为IoC,并为所有内容提供了代码示例。https://dev59.com/Vm855IYBdhLWcg3wQyDh - Paul
2个回答

6

使用依赖注入/控制反转框架,例如:

  1. Ninject
  2. Autofac
  3. StructureMap
  4. Unity

使用IoC容器,您可以告诉它如何管理单个数据上下文(通常是每个请求)。当您将数据上下文设置为每个请求时,容器会自动地为需要数据上下文的任何类提供相同的数据上下文。

这里有一篇关于设置Ninject的好文章

假设您正在使用通用存储库,您的代码最可能看起来像:

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();
    }
}

我喜欢依赖注入,但你仍应该在存储库内部实例化ObjectContext。例如,考虑一个由IoC容器配置为单例的存储库,并接收ObjectContext作为构造函数参数的后果。 - smartcaveman
太棒了,谢谢!不过我有几个问题。1)在Ninject Bind示例中,我正在使用EF4,你是从哪里获取上下文的Bind<MyDataContext>().ToSelf().InRequestScope();。MVC应用程序不应该知道EF的存在,对吗? - Andrew
你尝试将Ninject模块放在您的服务层中,然后只在您的ASP.NET MVC项目中引用它了吗? - Omar
所以上下文应该存在于服务层,然后您使用Ninject将其注入到所有需要它的对象中?Ninject将在MVC应用程序中创建它,并自动将其发送到存储库层,只需知道存储库需要它即可?UnitOfWork呢?您有任何示例吗?-谢谢! - Andrew

0
如果您的功能很简单,那么您应该在每个Repository中创建一个新的ObjectContext。它们很容易实例化。
如果这会创建冲突,您可以使用像评论中建议的工作单元模式。
我建议您在将ObjectContext或DataContext与DI容器集成时要非常谨慎。默认情况下,许多人不使用适当的生命周期范围。

在简单的情况下,为每个存储库提供新的上下文是可行的。但通常情况下,您会发现希望在多个存储库之间共享上下文。这通常通过使用UnitOfWork模式来处理。 - Ladislav Mrnka
@smart - 谢谢你提供链接,不过能否提供一个示例实现? - Andrew
and, http://devtalk.dk/2009/06/09/Entity+Framework+40+Beta+1+POCO+ObjectSet+Repository+And+UnitOfWork.aspx和,http://devtalk.dk/2009/06/09/Entity+Framework+40+Beta+1+POCO+ObjectSet+Repository+And+UnitOfWork.aspx - smartcaveman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接