记住.net中的SQL连接状态
本文关键字:连接 状态 SQL 中的 net 记住 | 更新日期: 2023-09-27 18:05:47
除了在已处理的连接上运行Close()
引发异常而在关闭的连接上运行Close()
之外,connection.Close()
与connection.Dispose()
是相同的旧事实-是OK的-我仍然有一个问题:
假设连接池是开启的,(默认)- 为什么记住连接的状态很重要?
我已经阅读了这个问题在这里显示- 避免打开和关闭连接节省性能。
这似乎合乎逻辑,但问题是连接是从来没有实际上关闭!只有标记了表示关闭。
即使我在using
作用域中使用它- dispose just 关闭连接并将其放回池中。
即使我想,我也不能让它开着(因为我想让别人使用它)。所以我不得不关闭/处理它。
查看同样实现此行为的Dapper:
public static async Task<IEnumerable<T>> QueryAsync<T>(this...)
{
//...
bool wasClosed = cnn.State == ConnectionState.Closed;
using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
{
try
{
if (wasClosed) await ((DbConnection)cnn).OpenAsync()...
//...
}
finally
{
if (wasClosed) cnn.Close();
}
}
}
你可以看到"记忆"
nb,我已经问过Marc一个相关的话题,那就是——为什么在dapper的样本中他同时使用GetClosedConneciton
和GetOpenConnection
,我得到的答案是——dapper可以处理这两种情况。然而,当前的问题是为什么重新设置连接状态
问题:
看看Dapper的代码,它似乎记住了状态,并在操作后重新设置状态。(我也从旧的sqldataadapter类中知道这种行为)
问题是——为什么?如果我有一个封闭的连接,那么,我需要打开它。太好了。但是为什么我要按条件关闭它呢?为什么不总是关闭它?这不会影响性能,因为连接实际上并没有关闭——它只是返回到池中。
反过来-如果我有一个打开的连接,那么我会做工作并保持打开 (huh?? ?)
正如你可能看到的,我在这里遗漏了一些东西。谁来点灯一下?为什么不总是关闭它?
用户可能正在该连接上执行大量工作。它可以与一个事务相关联(关闭它会孤立它)。它可以有临时表(关闭会销毁它们),或者其他连接保持状态(SET
选项、模拟等)。
在这里关闭连接(如果它最初是打开的)将是一种不寻常的和意想不到的事情,并且会产生多种严重的副作用。
如果你正在编写一个库函数,其中消费者向你传递一个连接对象(无论哪种类型)是有意义的,那么最安全的做法是尊重该连接:
- 如果你传递了一个打开的连接对象,不要对它做任何假设,当然也不要在你完成你的工作后关闭它——你不知道你的消费者对它做了什么或将对它做什么。
- 如果你传递了一个关闭的连接对象,那么你最好在你尝试使用它之前打开它,你应该在你完成后关闭它——你知道你的消费者不能有一个交易打开一个关闭的连接。
如果您的代码创建了一个连接对象,那么我总是建议将创建放在using
语句中,这样当您完成时它将始终关闭。
所以,我能想到的唯一剩下的事情就是仔细考虑编写你的函数,并弄清楚它是否使有意义让你的消费者传递给你连接对象-如果你的工作应该总是在隔离中执行,它会更有意义,例如要求一个连接字符串,并让你的代码完全控制连接。