C# 会话状态变量和单例类

C# 会话状态变量和单例类,c#,asp.net,.net,singleton,session-state,C#,Asp.net,.net,Singleton,Session State,我有一种情况,我需要从执行了将近半分钟的查询中检索数据,并将其带到网页。(无法减少此时间,因为已对其执行了最大数量的优化) 我为我的应用程序使用了四层体系结构和实体框架(EF、数据访问层、业务逻辑层、UI)。 我尝试在创建DAL的实例时使用singleton方法(DAL反过来从数据库检索数据),这样我就能够重用这个实例,因此在同一个会话中不会创建其他实例。 如何设置会话状态并检查状态服务器中实例的可用性 public static Singleton getInstance() { i

我有一种情况,我需要从执行了将近半分钟的查询中检索数据,并将其带到网页。(无法减少此时间,因为已对其执行了最大数量的优化) 我为我的应用程序使用了四层体系结构和实体框架(EF、数据访问层、业务逻辑层、UI)。 我尝试在创建DAL的实例时使用singleton方法(DAL反过来从数据库检索数据),这样我就能够重用这个实例,因此在同一个会话中不会创建其他实例。 如何设置会话状态并检查状态服务器中实例的可用性

public static Singleton getInstance() {
     if (**instance == null**)
       instance = new Singleton();
     return instance;
   }
如果
块中应该驻留什么?我应该在
if
块中检查什么条件?我真的不确定我必须做什么


PS:此会话的超时时间必须为5分钟。我听说这可以在Web.config文件中指定。这是真的吗?

我觉得您有一个定义良好的体系结构,适合依赖注入。使用DI,您可以让IOC容器返回一个单例对象或瞬态对象。但是,在web环境中使用单例时要非常小心,因为它们通常会带来更多的麻烦

如果您正在运行的查询包含特定于用户的数据,那么如果您使用的是控制器中的MVC模式或演示者中的MVP模式,那么我可能会将该查询的结果放入构成应用程序UI部分的代码中的会话中


如果这些模式没有被使用,那么您可以考虑将信息放入业务层内部的会话中,但只有在结束会话并将该依赖项注入业务对象时,例如“IUSER会话”之类的东西。业务项目不应包含对“system.Web”或类似内容的引用。

老实说,您应该使用实体框架上下文,并在每次需要访问数据库时(即在每个方法中)创建实体框架上下文。它经过优化,可以这样使用。连接池将确保每次重新创建EF上下文时不会受到惩罚。这是最好的做法

但DAL可能不仅仅是简单的数据库访问。如果您想将其作为单独的会话,则必须在第一次请求时创建实例,将其存储到会话中,并在使用之前检查它是否存在。使用线程安全性时,代码可能如下所示:

class DALClass
{
    private static object instanceLock = new object();

    public static DALClass Instance
    {
        get
        {
            if (Session["DALInstance"] == null)
            {
                lock (instanceLock)
                {
                    if (Session["DALInstance"] == null)
                    {
                        Session["DALInstance"] = new DALClass();
                    }
                }
            }

            return (DALClass)Session["DALInstance"];
        }
    }
}

会话是一个名称值集合。按名称获取DAL实例,然后检查该值是否为null。如果不为null,则将其转换为DAL的实例。无论如何,我不会遵循这种模式。创建DAL的成本如此之高,以至于您希望避免为每个请求创建和处理实例?您是否为每个用户会话创建单独的DAL?为什么DAL是特定于会话的?你不能为DAL建立一个工厂,上面有一个静态属性吗?调用属性时,查看DAL实例的工厂静态成员是否为
null
。如果是,则实例化并返回。如果没有,请返回。您可以发布有关DAL的内容吗?您希望实例保持活动状态这一事实可能会引发一些您应该注意的其他问题,例如保持连接打开等@krishna:每次创建DAL时都会触发存储过程?那似乎。。。奇怪。通常DAL有助于代码调用数据库资源,当应用程序还不需要这些资源时,它不应该在内部调用这些资源。另外,您所说的“我们希望数据不会在刷新时消失”是什么意思?这听起来像是希望在会话中(或在任何其他状态管理方法中)管理数据本身,而不是DAL本身。听起来好像你在为每一个会话创建一个新的DAL。所以每个用户都有自己的。克里希纳:我并不想说你的代码太苛刻,特别是因为除了问题中的一个小片段之外,我们看不到你的任何代码。这听起来就像你在寻找建议,在一个已经有缺陷的前提下继续前进。这一前提与我们其他人通常期望看到的情况严重脱节,因此我们无法真正给出一个连贯的答案。这里的关键点是,查询结果(而不是DAL)应该进入会话。会话对象本身已经具有您想要的所有特征:“不会在同一会话中创建其他实例”。(此外,如果您在SQL标记的问题中发布查询,您可能会得到一些优化它的帮助。30秒对于网页来说太长了,除非您的用户别无选择,只能使用它。)我认为DAL对象不应该是单例对象,也不应该缓存在会话中。缓存结果是,但不缓存执行工作的对象。最多DAL应该由DI处理,并在每个web请求上创建一次。参见castle文档:正如我在回答中指出的,在会话中使用DAL并不是最好的主意。除非还有更多,否则我们不知道。@Maciej:我把上下文放在会话中的实体上。好吗?@krishna,如果您指的是实体框架上下文(从ObjectContext继承的类),那么您应该在每次需要使用它时在每个方法中创建它。不要将其视为新的DB连接,因为它不是,而且创建起来相对便宜。