当前位置:  开发笔记 > 编程语言 > 正文

.net SqlConnection即使在使用{}内也没有关闭

如何解决《.netSqlConnection即使在使用{}内也没有关闭》经验,为你挑选了2个好方法。

请帮忙!

背景信息

我有一个WPF应用程序访问SQL Server 2005数据库.数据库在运行应用程序的计算机上本地运行.

无处不在我使用Linq DataContext我使用了一个using {}语句,并传入一个函数的结果,该函数返回一个已打开的SqlConnection对象,并在返回DataContext构造函数之前使用它执行了SqlCommand ..即

// In the application code
using (DataContext db = new DataContext(GetConnection()))
{
    ... Code 
}

getConnection看起来像这样(我从函数中删除了'fluff'以使其更具可读性,但没有其他功能缺失).

// Function which gets an opened connection which is given back to the DataContext constructor
public static System.Data.SqlClient.SqlConnection GetConnection()
{
   System.Data.SqlClient.SqlConnection Conn = new System.Data.SqlClient.SqlConnection(/* The connection string */);

    if ( Conn != null )
    {
        try
        {
            Conn.Open();
        }
        catch (System.Data.SqlClient.SqlException SDSCSEx)
        {
             /* Error Handling */
        }

        using (System.Data.SqlClient.SqlCommand SetCmd = new System.Data.SqlClient.SqlCommand())
        {
            SetCmd.Connection = Conn;
            SetCmd.CommandType = System.Data.CommandType.Text;

            string CurrentUserID = System.String.Empty;
            SetCmd.CommandText = "DECLARE @B VARBINARY(36); SET @B = CAST('" + CurrentUserID + "' AS VARBINARY(36)); SET CONTEXT_INFO @B";

            try
            {
                SetCmd.ExecuteNonQuery();
            }
            catch (System.Exception)
            {
                /* Error Handling */
            }
        }

        return Conn;
    }

我不认为作为WPF的应用程序对我遇到的问题有任何影响.

我遇到的问题

尽管SqlConnection与Sql Server Management Studio中的DataContext一起处理,我仍然可以看到大量的打开连接:

status : 'Sleeping' 
command : 'AWAITING COMMAND' 
last SQL Transact Command Batch : DECLARE @B VARBINARY(36); SET @B = CAST('GUID' AS VARBINARY(36)); SET CONTEXT_INFO @B

最终连接池用完了,应用程序无法继续.

因此,我只能得出结论,以某种方式运行SQLCommand来设置Context_Info意味着当DataContext被释放时连接不会被处理掉.

任何人都可以发现任何明显的东西,当它们被使用的DataContext被处理时,会阻止连接被关闭和处理吗?



1> Marc Gravell..:

来自MSDN(DataContext Constructor (IDbConnection)):

如果提供打开的连接,DataContext将不会关闭它.因此,除非您有充分的理由这样做,否则不要使用打开的连接实例化DataContext.

所以基本上,看起来你的连接正在等待GC在它们被释放之前完成它们.如果你有很多代码可以做到这一点,一种方法可能是覆盖Dispose()数据上下文的部分类,并关闭连接 - 只需确保记录数据上下文假定连接的所有权!

    protected override void Dispose(bool disposing)
    {
        if(disposing && this.Connection != null && this.Connection.State == ConnectionState.Open)
        {
            this.Connection.Close();
            this.Connection.Dispose();
        }
        base.Dispose(disposing);
    }

就个人而言,只要我"使用"连接(允许我执行多个操作),我很乐意给它(常规数据上下文,没有上面的黑客)开放连接 - 即

using(var conn = GetConnection())
{
   // snip: some stuff involving conn

   using(var ctx = new FooContext(conn))
   {
       // snip: some stuff involving ctx
   }

   // snip: some more stuff involving conn
}



2> Bradley Grai..:

SqlProvider由LINQ使用DataContext仅关闭SQL连接(通过SqlConnectionManager.DisposeConnection),如果它是一个将其打开.如果给构造函数一个已打开的SqlConnection对象DataContext,它将不会为您关闭它.因此,你应该写:

using (SqlConnection conn = GetConnection())
using (DataContext db = new DataContext(conn))
{
    ... Code 
}

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有