实体框架:Singletonish ObjectContext - 好、坏还是过于复杂?

9

这个想法是创建一个类,它暴露上下文但处理它在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),并在请求结束时被撤销。

如果这是一个单元测试的情况,它会在第一次需要时创建,并在TestCleanup中被移除(在本帖中不是很重要,但我只是想澄清_context对象)。

现在,至少不必再这样做:

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

每次我想要查询时,我意识到这可能是因为我懒惰,但我认为这样做更容易、更干净:

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

并避免“使用”,对于大多数情况我都尽量避免使用。此外,我不会在每次postback时创建9001个上下文。
现在我很好奇的是,我是否过于考虑了这个问题?我应该只为每个需要一个上下文的方法创建上下文吗?比如在postback时我必须:
- 通过ID获取用户 - 通过ID获取站点 - 将站点添加到用户中(user.Site = foundSite) - 保存用户
这可能至少涉及3个上下文。Entity Framework是否足够聪明,可以随时创建上下文呢?
3个回答

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

我并不知道这是一个确切的模式,但是我之前使用过nHibernate,并且正在尝试使用EF做同样的事情。基本上这就是我想要实现的。 - Programmin Tool
是的,有几种会话管理模式。最常见且正确的模式是每个请求一个会话,每个业务对话一个会话非常新颖。会话管理的反面模式是每个应用程序一个会话和每次调用一个会话(没有管理,在每次创建和销毁会话)。 - Chris Marisic

4

请查看这篇博客文章,它提供了有关为Entity Framework上下文创建单例以及为什么在ASP.NET中不起作用的更多细节,并提出了与您建议类似的解决方案。


1
如果您正在尝试实现类似于NHibernate的Session的东西,我认为拥有这种模式是一个好主意。我知道在LinqToSql中,上下文对象的实现更像是一个作为门面的入口类。我想LinqToEntities也是类似的。您可以有一个工厂实现来获取数据上下文到您的模型,从而可以回收数据上下文。如果您采用单例方式,请考虑单例对象的瓶颈、可用性和责任。

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