【问题标题】:Entity Framework: Singletonish ObjectContext - Good, Bad, or Overthinking?实体框架:Singletonish ObjectContext - 好、坏还是想太多?
【发布时间】:2010-10-07 06:07:22
【问题描述】:

这个想法是创建一个公开上下文但在 Web 应用程序中处理它的存储的类。

目前这是我所拥有的:

public class EntityContext
{

    private static String MAIN_CONTEXT_KEY = "MainContext";
    private static TISQLEntities _context;

    public static void RemoveContext()
    {
        if (
            HttpContext.Current != null 
            && 
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] != null
           )
        {
            ((TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY]).Dispose();
            HttpContext.Current.Items[MAIN_CONTEXT_KEY] = null;
        }

        if (_context != null)
        {
            _context.Dispose();
            _context = null;
        }
    }

    public static TISQLEntities Context
    {
        get
        {
            if (HttpContext.Current == null)
            {
                if (_context == null)
                {
                    _context = new TISQLEntities();
                }

                return _context;
            }

            if (HttpContext.Current.Items[MAIN_CONTEXT_KEY] == null)
            {
                HttpContext.Current.Items[MAIN_CONTEXT_KEY] = new TISQLEntities();
            }

            return (TISQLEntities)HttpContext.Current.Items[MAIN_CONTEXT_KEY];
        }
    }
}

然后在 Global.asax 文件中:

protected void Application_EndRequest(object sender, EventArgs e)
{
    EntityContext.RemoveContext();
}

这个想法是,如果这是通过 Web 应用程序运行的,上下文会在第一次需要时创建(并保存到当前的 HttpContext),并在请求结束时删除。

如果这是 UnitTest 情况,则反对在第一次需要时创建并在 TestCleanup 中删除(在这篇文章中并不重要,只是想澄清 _context 对象)。

现在这背后的想法是至少不必这样做:

using(TISQLEntities context = new TISQLEntities())
{
  ....
}

每次我想查询。我意识到这可能是我懒惰,但我只是认为它更容易更干净:

EntityContext.Context.User.Select(...)

并且避免在大多数情况下我尽量避免的“使用”。最重要的是,我不会在每次回发时创建 9001 个上下文。

现在我很好奇的是,我是不是在想这个?我应该继续为每个需要的方法创建一个上下文吗?在回帖中说我必须:

  • 通过 ID 获取用户
  • 从 id 获取网站
  • 将站点添加到用户 (user.Site = foundSite)
  • 保存用户

这可能需要至少 3 个上下文。实体框架是否足够聪明,可以随时继续创建上下文?

【问题讨论】:

    标签: asp.net entity-framework


    【解决方案1】:

    您正在实现 NHibernate 的每个请求会话模式的等效项,这是 NHibernate 中的一个很好的构造。虽然我不能说 100% 肯定它适用于 EF,但它很可能是适用的。对其他会话管理模式的进一步扩展是每个业务会话的会话,它允许 NHibernate 通过断开和重新连接会话而不是销毁和创建会话来在 HttpSession 的持续时间内延长保持会话的时间。如果 EF 允许类似的功能而不是保持静态开放连接,您可以通过我的个人资料在我的博客上查看我是如何使用 AOP 实现该模式的。

    【讨论】:

    • 我不知道这完全是一种模式,但是我以前使用过 nHibernate 并且试图对 EF 做同样的事情。这基本上就是我想要实现的目标。
    • 是的,有一些会话管理模式。最常见的正确模式是每个请求的会话,每个业务会话的会话是非常新的,会话管理的反模式是每个应用程序的会话和每个调用的会话(没有管理,每次都创建和销毁会话)
    【解决方案2】:

    如果您尝试使用 NHibernate 的 Session 来实现类似的功能,我认为拥有这种模式是个好主意。我确信在 LinqToSql 中,上下文对象的实现更像是一个入口点类,它充当一个门面。我想认为 LinqToEntities 是相似的。您可以有一个工厂实现来为您的模型获取数据上下文,您可以在其中回收数据上下文。如果您采用单例方式,请考虑单例对象的瓶颈、可用性和责任。

    【讨论】:

      【解决方案3】:

      查看this blog entry,它提供了有关为实体框架上下文创建单例的更多详细信息,以及为什么这在 ASP.NET 中不起作用,并提出了与您建议的类似的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-04
        • 1970-01-01
        • 2013-11-26
        • 2013-03-07
        • 1970-01-01
        • 2011-07-30
        相关资源
        最近更新 更多