记住.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的样本中他同时使用GetClosedConnecitonGetOpenConnection,我得到的答案是——dapper可以处理这两种情况。然而,当前的问题是为什么重新设置连接状态

问题:

看看Dapper的代码,它似乎记住了状态,并在操作后重新设置状态。(我也从旧的sqldataadapter类中知道这种行为)

问题是——为什么?如果我有一个封闭的连接,那么,我需要打开它。太好了。但是为什么我要按条件关闭它呢?为什么不总是关闭它?这不会影响性能,因为连接实际上并没有关闭——它只是返回到池中。

反过来-如果我有一个打开的连接,那么我会做工作并保持打开 (huh?? ?)

正如你可能看到的,我在这里遗漏了一些东西。谁来点灯一下?

记住.net中的SQL连接状态

为什么不总是关闭它?

用户可能正在该连接上执行大量工作。它可以与一个事务相关联(关闭它会孤立它)。它可以有临时表(关闭会销毁它们),或者其他连接保持状态(SET选项、模拟等)。

在这里关闭连接(如果它最初是打开的)将是一种不寻常的和意想不到的事情,并且会产生多种严重的副作用。

如果你正在编写一个库函数,其中消费者向你传递一个连接对象(无论哪种类型)是有意义的,那么最安全的做法是尊重该连接:

  • 如果你传递了一个打开的连接对象,不要对它做任何假设,当然也不要在你完成你的工作后关闭它——你不知道你的消费者对它做了什么或将对它做什么。
  • 如果你传递了一个关闭的连接对象,那么你最好在你尝试使用它之前打开它,你应该在你完成后关闭它——你知道你的消费者不能有一个交易打开一个关闭的连接。

如果您的代码创建了一个连接对象,那么我总是建议将创建放在using语句中,这样当您完成时它将始终关闭。

所以,我能想到的唯一剩下的事情就是仔细考虑编写你的函数,并弄清楚它是否使有意义让你的消费者传递给你连接对象-如果你的工作应该总是在隔离中执行,它会更有意义,例如要求一个连接字符串,并让你的代码完全控制连接。