试图避免嵌套的SqlConnection

时间:2014-04-09 07:12:54

标签: c# sqlconnection

我甚至不确定嵌套SqlConnections是否可行,但我真的想远离它。我现在在我的代码中遇到了一个范围问题,我试图弄清楚如何绕过它。

所以直到最近我才有了一个全局SqlConnection,它在应用程序启动时打开,在完成时关闭。我现在已经发现了.NET连接池的概念,所以我改变了我的代码,以便每个SqlCommand(或其中一组)使用自己的,新创建和打开的, SqlConnection,信任.NET来管理池和随之而来的开销。

我现在面临的问题是,我有几个代码块,看起来像这样:

using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{       
    sqlConnection.Open();
    using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection))
    {
        sqlCommand1.ExecuteNonQuery();
    }
    using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection))
    {
        sqlCommand2.ExecuteNonQuery();
    }
    .
    .
    .
    ClassGlobal.WriteAction(action);
}

而ClassGlobal.WriteAction()函数看起来像这样:

public static void WriteAction(MyActionClass action)
{
    using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
    {       
        sqlConnection.Open();
        using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection))
        {
            sqlCommand.ExecuteNonQuery();
        }
    }
}

如您所见,在SqlConnection内创建了一个新的WriteAction(),它是从第一个SqlConnection范围内调用的。不好!我试图避免这种情况。

在过去,由于没有这些using (SqlConnection)块而且所有SqlCommands都指向同一个(全局)SqlConnection,所以不会出现问题。显然,我可以简单地将WriteAction()的调用移到using (SqlCommand)的结束大括号下方,但是:

  1. 我传递给它的action实例经常在SqlConnection的范围内进行实例化和填充,因此我必须进行更多更改(大量更改)以移动这些实例超出SqlConnection范围。有很多它们会很多毛。
  2. 我真的更喜欢WriteAction()调用可以在SqlConnection范围内,如上例所示,这样我就可以将所有内容都包含在TransactionScope中到目前为止,这是不可能的,但肯定是个好主意。
  3. 所以这就是我打算做的事情,但我想听听你们是否会认为这不是一个好的做法,或者你是否可以建议一个更好的方法。 (我最近发现我的全球SqlConnection并不是一个很好的做法,而且它花了很多时间来修复它。我希望将来避免这样的发现。)

    如何向WriteAction()函数添加参数,使其如下所示:

    public static void WriteAction(MyActionClass action, SqlConnection sqlConnection)
    {   
        using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection))
        {
            sqlCommand.ExecuteNonQuery();
        }
    }
    

    这意味着,我可以简单地将WriteAction()作为参数添加到函数的SqlConnection,而不是将调用移到SqlConnection范围之外的SQLCommand。函数内部使用相同的连接,即使该连接已登记到TransactionScope

    对于我从任何WriteAction()范围之外调用SqlConnection的少数实例,我可以编写一个如下所示的重载函数:

    public static void WriteAction(MyActionClass action)
    {
        using (TransactionScope transactionScope = new TransactionScope())
        {
            using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
            {
                sqlConnection.Open();
                WriteAction(action, sqlConnection);
            }
            transactionScope.Complete();
        }
    }
    

    这看起来是个好主意还是我将在两年内再次做出这个决定?

1 个答案:

答案 0 :(得分:2)

SqlConnection实例传递给方法绝对没问题。但是,我不确定你是否采用最后的方法,没有SqlConnection的重载方法是个好主意。它隐藏了一个事实,你应该更好地使用另一个新的重载。它使代码编译阻止你修复现在应修复的代码。

请注意,using块不是问题,而是打开的连接。只要您不打开连接,连接池就不需要打开物理连接。

因此,在致电WriteAction之前关闭连接也是一个可行的选择:

using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{       
    sqlConnection.Open();
    using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection))
    {
        sqlCommand1.ExecuteNonQuery();
    }
    using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection))
    {
        sqlCommand2.ExecuteNonQuery();
    }
    // ...
    sqlConnection.Close();

    ClassGlobal.WriteAction(action);

    // ... perhaps open it again here
}

来自MSDN

  

每当用户在连接上调用Open时,pooler会查找   池中的可用连接。如果有可用的池连接,   它将它返回给调用者而不是打开新连接。什么时候   应用程序在连接上调用Close,pooler返回它   汇集到一组活动连接而不是关闭它。一旦   连接返回到池中,可以重新使用它   下一次Open来电。

因此,您可以看到using中的嵌套WriteAction不是问题,只要您不保持外部连接打开即可。不要将连接实例与物理连接混淆。