是否最好将打开的SqlConnection作为参数传递,或者在每个方法中调用一个新的?

时间:2012-03-21 15:04:28

标签: c# sqlconnection

如果我要调用的方法/函数需要打开SqlConnection,我将在调用该函数的方法中打开它。例如:

protected static void btnSubmit(){
   conn.Open();
   myMethod(someParam, conn);
   conn.Close();
}

protected static void myMethod(object someParam, SqlConnection conn){
   //Some SQL commands etc here..
}

我这样做是为了我:

  • 每个进程只能打开和关闭1个SqlConnection

然而,如此构造我的代码会更好:

protected static void btnSubmit(){
   myMethod(someParam);
}

protected static void myMethod(object someParam){
   SqlConnection conn = New SqlConnection(".....");
   conn.Open();
   //Some SQL commands etc here..
   conn.Close();
}

我看到以这种方式构建它的优点是:

  • 我不必为每个方法传递额外的参数
  • 如果稍后该方法不再具有SQL命令,则每次都不会调用未使用的参数

我看到的缺点是:

  • 如果myMethod是一种递归方法,那么当它自己调用时,它将打开另一个SqlConnection,依此类推,等等......
  • 如果btnSubmit正在调用多个需要SqlConnection的方法,则每个方法都将打开并关闭一个新连接。

这样做的最佳方法是什么,哪种方式最常用?

2 个答案:

答案 0 :(得分:16)

ADO.NET使用连接池,因此即使您认为要打开新连接,它也会自动重用已打开的连接。考虑到这一点,没有理由通过代码传递连接(作为参数)。这将使您的代码更清晰,具有与将连接作为参数传递时相同的性能。

更多详情here

另外(这非常重要),请使用“using”关键字。通过这种方式,您不必关闭连接和清理,因为现在编写的代码不处理关闭连接,因此在某些异常的情况下,您最终可能会遇到连接限制你的服务器。去做这样的事情:

using(var connection = new SqlConnection(<connection_string>))
{
  connection.Open();
  using(var command = connection.CreateCommand())
  {

  }
}

如您所见,无需调用connection.Close()或处理异常并关闭finally块中的连接,因为这是“使用”块的“作业”。

另外,一个重要的注意事项......事务不是通过连接轮询传递的,所以如果你想让你的事务跨越方法调用,你必须通过你的连接(这是我能想到为什么的唯一原因)你应该这样做。)

答案 1 :(得分:11)

使用的最佳模式是Repository + UnitOfWork模式。

因此创建存储库并传递包含连接的UnitOfWork。完成工作后,UnitOfWork将被处理掉。

// Pseudocode
using(UnitOfWork uow = new UnitOfWork())
{
   Repository.Init(uow);
   Repository.SaveInDb(stuff);
}

工作单位:

// PseudoCode
class UnitOfWork : IDisposable
{
   public UnitOfWork()
   {
      conn = new SqlConnection();
      conn.Open();
   }

   public void Dispose()
   {
       conn.Close();
   }

 ....

}

这是我一直使用的。

有些人更喜欢简单的方法,其中Repository拥有连接。这更简单,但是如果您需要跨多个存储库进行事务,它将无法工作。