EF DBContext dispose未关闭连接

24

我正在使用EF 6.1.0版本。

我有以下自定义的DBContex对象,命名为DBEntites。

public partial class DbEntities : DbContext
{
    public DbEntities()
        : base("name=DbEntities")
    {
        ////Configuration.LazyLoadingEnabled = true;
        ////Configuration.ProxyCreationEnabled = false;
    }

    //// I have ALL Entites added as below
    ////public virtual IDbSet<CCode> CCodes { get; set; }
}

我对上下文对象执行以下操作

using (var context = new DbEntities())
        {
            var entitySet = context.Set<T>();
            var res = entitySet.Where<T>(predicate).ToList();
            if (context.Database.Connection.State == ConnectionState.Open)
            {
                context.Database.Connection.Close();
            }

            return res;
        }

但是在处理完上下文对象后,我仍然可以看到一个活动的数据库连接。在连接状态条件下,我可以看到该连接已关闭(该连接从未为真)。

我正在使用以下查询来查看SQL上的连接。

select db_name(dbid) , count(*) 'connections count'
from master..sysprocesses
where spid > 50 and spid != @@spid
group by db_name(dbid)
order by count(*) desc

以下语句会增加 SQL 连接计数。但即使在处理完毕后也没有减少连接计数,也就是说,在 using 块执行完毕后应该关闭连接。

var res = entitySet.Where<T>(predicate).ToList();
任何帮助都将不胜感激。

3
很可能是由于连接池的缘故:打开和关闭连接是耗费资源的,因此.NET会保留一些连接并重复使用它们。https://msdn.microsoft.com/zh-cn/library/8xx3tyca(v=vs.110).aspx - Evk
希望是这样的。但在我的情况下,我并没有重复使用相同的连接对象。所以对我来说没有用处。 - Chandra Mohan
5
这并不是关于重复使用连接对象。当您使用相同的配置(连接字符串)创建新的连接时,它实际上不会打开新的数据库连接,而是重用现有的连接(如果连接池中已存在)。同样,当您关闭连接对象时,底层连接可能不会被关闭,而是被放入连接池中。由于您很可能在应用程序的生命周期内多次查询同一数据库 - 这对您将会很有用。 - Evk
请将以下与编程相关的内容从英语翻译成中文。只返回翻译后的文本:确保翻译通顺,我会确认并标记为答案。 - Chandra Mohan
我想在你把它作为答案发布之前,我无法将其标记为答案。 - Chandra Mohan
显示剩余2条评论
2个回答

29

正如评论中所发现的那样,原因确实是由.NET执行的连接池。为了提高性能(因为频繁开关连接可能会影响性能),.NET为您应用程序中使用的每个连接字符串维护一个连接池。该池具有一定的最小和最大大小(由MinPoolSizeMaxPoolSize连接字符串参数控制)。当您打开一个连接(通过SqlConnection.Open)时,它可能会被从池中取出而不是真正地重新打开。当您关闭连接(这也是通过处理EF上下文完成的)时,连接可能会被放回到池中,而不是真正关闭。当连接闲置一段时间(约5分钟)后,它可能会从池中移除。

如果您(出于某种原因)想要避免这种情况,您可以将MaxPoolSize设置为0(对于您的连接字符串),或者通过使用SqlConnection.ClearPoolSqlConnection.ClearAllPools来显式清除池。


-2

在这里分享我的经验。我在使用EF Core 6 + Postgres时遇到了同样的问题,解决方法就是在连接字符串中禁用“Pooling”。

Pooling=false;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接