我相信在使用LINQ时无法获得sql连接泄漏,但NumberOfReclaimedConnections的perfmon跟踪显示数字很高,在高负载时我们有时会遇到“Timeout expired”之类的异常。在获取连接之前已经过了超时时间这可能是因为所有池连接都在使用中并且达到了最大池大小“。
我们不在datacontexts上使用Dispose,因为我们使用了deferred loading。一些文章和博客文章告诉我,这应该不是问题。
我们有时会得到这些例外。但是,我们所做的每个linq查询都不能保持连接打开,那么我们会有更多的例外。
被修改
该应用程序是一个WCF服务。
如果您查看Linq和大多数文章的文档,他们声称不需要Dispose来释放连接。他们声称DataCOntext仅在需要的短时间内保持连接打开。
答案 0 :(得分:10)
当您的DataContext
未被处置并保持活动状态时,关联的连接也将保持活跃状态。数据库连接是非托管资源,必须正确处理所有非托管资源。
即使您使用延迟加载并且没有明确定义的范围,您仍应在逻辑工作单元结束时清理数据库连接。在ASP.NET应用程序中,最新的可能时刻是在请求处理结束时 - 在Globals.asax文件的Application_EndRequest方法中。在WCF服务中,任何活动数据上下文都应在每个服务方法调用结束时处理。
这方面的文档很模糊,而且大多数时候,你可以放弃不处理你的DataContext,似乎确实存在从连接加载的数据保持连接本身存在的一些场景。确认在您的情况下发生这种情况的最简单方法是测试它。
答案 1 :(得分:4)
我发现经过一些搜索后我找到了这个question and answer,其中说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;
}
如果我在上下文中添加了一个处理调用,它们会消失。
答案 2 :(得分:0)
您是否在数据库中遇到任何死锁?快速查看活动监视器应该给你一些指示。
您如何管理DataContext生命周期 - 您编写了哪种应用程序(网站,Windows客户端,其他)?
一旦在查询或操作中使用,DataContext将保持连接,以便加载的实体可以延迟加载&amp;等等,因此您必须规划在应用程序中使用DataContexts的方式。
WCF服务..在这种情况下,我是“每个请求一个上下文”方法的忠实粉丝。我鼓励您将数据操作包装在using()语句中,以便在完成后处理上下文。