会话变量丢失 - Singleton实例变为null

时间:2012-09-26 13:41:49

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

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

创建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 App上,我有一个Master Page,通过检查Session变量来控制用户是否登录。如果此会话为空,则将用户发送到登录页面。

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

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

它们被发送回登录页面的事实意味着Session变量丢失,显示的消息意味着“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

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

2 个答案:

答案 0 :(得分:0)

应用程序池有一个属性,使其每N分钟自动回收一次(默认为1740,或每29小时。)将此值设为零以禁用回收。该物业是(在IIS7上)在“回收”标题下,被称为“常规时间间隔(分钟)”

enter image description here

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

我之所以提到它是因为:

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

答案 1 :(得分:0)

您不应该保持与数据库的连接打开。通常会为每个请求打开一个新连接。也许数据库有时会判断它有太多用户或连接打开的时间太长,因此它会关闭连接并导致对象崩溃。与数据库的开放连接也存在安全风险。

虽然我不是100%肯定...

您应该将连接到数据库的内容移到某种查询执行方法。同时加载这样一团数据似乎是不明智的,你不能在后台进行,或者只加载用户当时需要看到的信息吗?