6

我相信在使用 LINQ 时不可能出现 sql 连接泄漏,但是 NumberOfReclaimedConnections 的 perfmon 跟踪显示一个高数字,并且在高负载时,我们有时会遇到异常,例如“超时已过期。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且达到了最大池大小”。

我们不对数据上下文使用 Dispose,因为我们使用了延迟加载。几篇文章和博文告诉我,这应该不是问题。

有时我们仍然会遇到这些异常。但是不可能每个 linq 查询都保持连接打开,那么我们会有更多的异常。

已编辑

该应用程序是 WCF 服务。

如果您查看 Linq 的文档和大多数文章,他们声称 Dispose 不是释放连接所必需的。他们声称 DataCONtext 仅在需要的短时间内保持连接打开。

4

3 回答 3

11

当您DataContext没有被处理并保持活动状态时,关联的连接也将保持活动状态。数据库连接是非托管资源,所有非托管资源都必须妥善处理。

即使您使用延迟加载并且没有明确定义的范围,您仍然应该在逻辑工作单元结束时清理数据库连接。在 ASP.NET 应用程序中,最晚的可能时刻是请求处理结束时 - 在 Globals.asax 文件的 Application_EndRequest 方法中。在 WCF 服务中,任何活动数据上下文都应该在每个服务方法调用结束时被处理掉。

这方面的文档含糊不清,虽然在大多数情况下,您可以避免不处理 DataContext,但似乎确实存在一些从连接加载的数据使连接本身保持活动状态的情况。确认您的情况发生这种情况的最简单方法是对其进行测试。

于 2009-04-23T06:16:21.113 回答
4

经过更多搜索后,我发现我找到了这个问题和答案,它说 linq 可以被愚弄以保持连接打开..

我制作了这个重现它的小测试代码。如果我只是用 foreach 替换 Enumerator 它工作正常,但他 Enumerator 保持连接打开。

public Organisation RunTestQuery2()
{
    IEnumerable<Organisation> orgs  = base.GetEntities<Organisation>().Take(5);

    var enumerator = orgs.GetEnumerator();
    int i = 0;


    while (enumerator.MoveNext())
    {
        var org = enumerator.Current;
        Debug.WriteLine(org.DescribingName);
        if (i == 3)
        {
           return org;
        }
        i++;
    }

    return null;
}

如果我在上下文中添加调用 dispose ,它们就会消失。

于 2009-04-23T07:30:57.940 回答
0

您的数据库中是否出现死锁?快速查看活动监视器应该会给您一些指示。

您如何管理 DataContext 生命周期 - 您编写了哪种应用程序(网站、Windows 客户端等)?

一旦在查询或操作中使用,DataContext 将保持连接,以便加载的实体可以延迟加载等,因此您必须计划如何在应用程序中使用 DataContexts。

WCF 服务.. 在这种情况下,我非常喜欢“每个请求一个上下文”方法。我鼓励您将数据操作包装在 using() 语句中,以便在完成后处理上下文。

于 2009-04-23T06:15:14.533 回答