【问题标题】:Session variables lost - Singleton instance becomes null会话变量丢失 - 单例实例变为空
【发布时间】:2012-09-26 13:41:48
【问题描述】:

我正在使用 ASP.NET 开发一个 Web 应用程序。我有一个名为“Sistema”的类,它使用单例模式。

创建 Sistema 实例时,会打开数据库连接并运行一个进程,该进程会加载一些静态信息以供以后使用。这将持续将近 2 分钟。

private static Sistema instance;
private Sistema()
{
    OpenDataBase();
    LoadStaticInformation();
}

public static Sistema GetInstance()
{
    if (instance == null)
    {
        instance = new Sistema();
    }
    return instance;
}

我保持与数据库的连接打开的原因是因为我使用的是 db4o,这强烈暗示了这一点。以下是一些参考资料:

db4o best practice to query objects from db

Is it OK to open a DB4o file for query, insert, update multiple times?

Query regarding database connectivity in db4o

在我的 Web 应用程序上,我有一个母版页,通过检查 Session 变量来控制用户是否登录。如果此 Session 为空,则将用户发送到登录页面。

在登录页面上,我要做的第一件事是检查“Sistema”的实例是否为空。如果是,那么当用户点击提交按钮时,会显示一条消息,上面写着“登录可能需要最多两分钟。请稍候”。如果它不为 null,则不会显示任何消息,因为登录操作只需几秒钟。

用户告诉我,在通过系统时,他们有时会被送回登录页面,当他们尝试登录时,会显示“登录可能需要最多两分钟”的消息,并且登录确实需要一段时间。

它们被发送回登录页面意味着会话变量丢失,显示的消息意味着“Sistema”的实例也为空。

为了确定发生这种情况的原因,我创建了一个网页,当检测到 Sistema 实例为空时,它会向我发送一封电子邮件。我想如果我能够知道这件事发生的时间,我可能会发现发生了什么。

这个网页真的很简单。它每 10 分钟运行一次并检查 Sistema 的实例是否为空。如果是,则发送电子邮件并创建 Sistema 实例。

bool isInstanceNull = Sistema.IsInstanceNull();
if (isInstanceNull)
{
    String emailTo = "...";
    String emailContent = "...";
    Functions.SendMail(emailTo, "Sistema is null", emailContent, "");

    Sistema.GetInstance();
    Functions.SendMail(emailTo, "Sistema has been created", emailContent, "");
}

我发现的唯一一件事是它不是在特定时间发生的。例如,上周发生在晚上 7 点左右,但今天发生在凌晨 2 点。

关于会话超时,我在后面的代码中使用了一个解决方案:http://www.beansoftware.com/ASP.NET-Tutorials/Keep-Session-Alive.aspx

对为什么会发生这种情况有任何建议吗?

【问题讨论】:

    标签: c# asp.net singleton session-variables session-timeout


    【解决方案1】:

    应用程序池有一个属性,它会导致它每 N 分钟自动回收一次(默认为 1740 或每 29 小时)。将此设置为零以禁用回收。该属性位于“回收”标题下(在 IIS7 上),称为“常规时间间隔(分钟)”

    除此之外,您应该立即始终关闭连接,并且在 ASP.NET 中根本不要使用static 连接(当默认启用连接池时)。

    我提到它是因为:

    private static Sistema instance;
    private Sistema()
    {
        OpenDataBase();
        LoadStaticInformation();
    }
    

    【讨论】:

    • 嗨蒂姆,感谢您的快速回复。我没有意识到这一点!我将尝试输入 0 以查看是否是导致问题的原因。关于您对连接的评论,我正在使用强烈建议保持连接有效的 db4o。如果您想检查,我已经用一些参考资料编辑了我的问题。谢谢!
    【解决方案2】:

    您不应保持与数据库的连接处于打开状态。通常,每个请求都会打开一个新连接。也许数据库有时会决定它有太多用户或连接打开时间过长,结果它关闭了连接并且您的对象崩溃了。与数据库的开放连接也是一种安全风险。

    不过,我对此不是 100% 确定...

    您可能应该将连接数据库转移到某种查询执行方法。另外一次加载这么一大堆数据似乎是不明智的,你不能在后台加载还是只加载用户当时需要看到的信息?

    【讨论】:

    • 嗨 Mr.Fox,感谢您的快速回复。我正在使用强烈建议保持连接有效的 db4o。如果您想检查,我已经用一些参考资料编辑了我的问题。谢谢!
    猜你喜欢
    • 2011-04-15
    • 1970-01-01
    • 2011-12-05
    • 2011-03-09
    • 2012-10-18
    • 1970-01-01
    • 2012-01-10
    • 2020-01-09
    相关资源
    最近更新 更多