是否最好将打开的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的多个方法,则每个方法都将打开并关闭一个新连接。
这样做的最佳方法是什么,哪种方法最常用?
ADO.NET使用连接池,因此即使您认为要打开新连接,它也会自动重用已打开的连接。 考虑到这一点,没有理由通过代码传递连接(作为参数)。 这将使您的代码更清晰,具有与将连接作为参数传递时相同的性能。
更多细节在这里
另外(这非常重要),请使用“using”关键字。 以这种方式,您不必关闭连接和清理,因为您现在编写的代码不处理关闭连接,因此在某些exception的情况下您最终可能会遇到连接限制你的服务器。 去做这样的事情:
using(var connection = new SqlConnection()) { connection.Open(); using(var command = connection.CreateCommand()) { } }
如您所见,无需调用connection.Close()或处理exception并关闭finally
块中的连接,因为这是“using”块的“作业”。
另外,一个重要的注意事项……事务不是通过连接轮询传递的,所以如果你想让你的事务跨越方法调用,你将不得不通过你的连接(这是我能想到为什么你应该做的唯一原因)那)。
使用的最佳模式是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拥有连接。 这更简单,但是如果您需要跨多个存储库进行事务,则它将无法工作。