【问题标题】:What is the best way to create EF DbContext instance for ASP.NET MVC为 ASP.NET MVC 创建 EF DbContext 实例的最佳方法是什么
【发布时间】:2012-03-19 05:00:36
【问题描述】:

为了在 EF 中支持延迟加载功能,实例化DbContext 的最佳方式是什么?

我知道HttpContext的当前项目是通过Application_BeginRequest方法和Application_EndRequest方法创建DbContext的好地方,但是在MSDN和官方asp.net mvc站点的一些示例代码中,他们只是创建@ 987654326@在Controller的构造函数中,并在控制器的Dispose()方法中处理。

我认为这两种方式并没有太大的不同,因为所有这些都实现了每个请求模式的会话。

我只是想确定我的理解是否正确。

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework


    【解决方案1】:

    控制器中的Dispose() 方法并不总是可靠的。同样的道理,Session 也可能不是一个好主意。 “最佳”可能是主观的,但我们通过使用依赖注入 (Castle Windsor) 并遵循工作单元存储库模式取得了最大的成功。

    按照以下方式设置工作单元:

    public class UnitOfWork : IUnitOfWork
    {
        public UnitOfWork()
        {
            this.Context = new MyEFEntities();
            this.Context.ContextOptions.LazyLoadingEnabled = true;
        }
    
        public void Dispose()
        {
            this.Context.Dispose();
        }
    
        public ObjectContext Context { get; internal set; }
    }
    

    设置您的存储库:

    public class Repository<TEntity> : IRepository<TEntity>
        where TEntity : class
    {
        public Repository(IUnitOfWork unitOfWork)
        {
            Context = unitOfWork.Context;
            ObjectSet = Context.CreateObjectSet<TEntity>();
        }
        public ObjectContext Context { get; set; }
        public IObjectSet<TEntity> ObjectSet { get; set; }
    }
    

    在 Global.asax 中向 Castle 注册:

    void Application_Start()
    {
        this.Container.Register(
            Component.For<IUnitOfWork>()
                .UsingFactoryMethod(() => new UnitOfWork())
                .LifeStyle
                .Is(LifestyleType.PerWebRequest)
            );
    
        ControllerBuilder.Current.SetControllerFactory(
            new WindsorControllerFactory(this.Container));
    }
    

    并在您的控制器中使用(或在您使用它的任何地方,只要它是可注射的):

    public class SomeController
    {
        public SomeController(IRepository<MyEntity> repository)
        {
            this.Repository = repository;
        }
    
        public IRepository<MyEntity> Repository { get; set; }
    
        public ActionResult MyAction()
        {
            ViewData.Model = this.Repository.ObjectSet.Single(x => x.Condition); //or something...
        }
    }
    

    【讨论】:

    • 感谢您的回复 lukiffer,但我的问题集中在更基本的东西上,而不是存储库,而不是 DI 的东西。我只是想知道在开始/结束请求事件或控制器类中哪种方法最好,而不使用存储库和 DI 容器。
    • 通过附加到开始/结束请求事件,您将可以在请求的整个生命周期中访问数据上下文的相同实例,不仅在控制器中(例如过滤器等),而且最终他们是一样的。我提出冗长解释的唯一原因是因为我在网络农场/网络花园的请求上下文中跟踪事物时遇到了问题,而这最终是唯一有效的方法。
    • 你的意思是两种方式都支持延迟加载,对吧?
    【解决方案2】:

    此处的任何延迟加载都可能成为未来问题的陷阱。没有 DI,没有存储库 - 如果没有延迟加载的黑客,很难看到任何工作。您还打算将实体传递给您的视图。如果是这样,这将造成不好的重叠。控制器应该为您的视图打包数据,而不是稍后在您的视图中进行评估。

    对于 MVC 最佳实践,您应该尽可能将域模型展平为视图模型(如果展平有意义)并使用该视图模型。由于理想情况下您会知道什么是延迟加载的,因此在查询中使用 .Include() 来预先加载可能更有意义,否则您可以向数据库发出许多查询。

    【讨论】:

      【解决方案3】:

      我使用了会话工厂模式并将 DBContext 保存在会话对象中。它将在每个会话中保持打开状态。到目前为止,我还没有遇到任何问题。

      【讨论】:

        猜你喜欢
        • 2011-10-22
        • 2020-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-10
        • 2011-07-12
        • 2010-09-12
        • 1970-01-01
        相关资源
        最近更新 更多