c# - 让 .net SqlConnection 无限期打开与 using 块
问题描述
我有一个深入的问题。我想了解 aSqlConnection
关闭的原因以及如何检测连接池是否实际发生。
我有两个不同版本的类,它们抽象与数据库对话并返回DataTable
. 我提供的是问题/问题的一个例子。
版本 1SqlConnection
在实例化时打开 a 并使其保持打开状态。这是一个单线程进程,它处理传入的消息并将结果尽快写入数据库。SqlConnection
这就是永久开放背后的想法:
public class SpecialDbClientVersion1 : IDisposable
{
string connStr;
SqlConnection dbConn;
public SpecialDbClientVersion1(string connStr)
{
this.connStr = connStr;
this.dbConn = new SqlConnection(connStr);
try
{
dbConn.Open();
}
catch (SqlException ex)
{
throw new Exception($"An exception occurred while trying to connect to {dbConn.Database}", ex);
}
}
public DataTable QuerySqlReturnResultAsDataTable(string sql, int commandTimeout = 30)
{
try
{
var cmd = new SqlCommand(sql, dbConn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = commandTimeout;
var dt = new DataTable();
var adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
return dt;
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message);
}
}
public void Dispose()
{
dbConn.Dispose();
}
}
当我对此进行测试时,一切都很好,并且吞吐量非常高。最终虽然由于SqlConnection
某种原因关闭了。抛出错误,聚会结束。
问题 1:有人可以解释什么会导致此连接进入Closed
状态而无需我调用该Close()
方法?
现在版本 2 在一个using
块中执行所有工作。根据互联网,运行时应该在后台神奇地使用连接池。SqlConnection
这是按照 Microsoft处理对象的最佳实践。使用连接池应该不会对性能造成太大影响。
public class SpecialDbClientVersion2
{
string connStr;
SqlConnection dbConn;
public SpecialDbClientVersion2(string connStr)
{
this.connStr = connStr;
}
public DataTable QuerySqlReturnResultAsDataTable(string sql, int commandTimeout = 30)
{
using(var dbConn = new SqlConnection(connStr))
{
try
{
var cmd = new SqlCommand(sql, dbConn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = commandTimeout;
var dt = new DataTable();
var adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
return dt;
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message);
}
}
}
}
问题 2:如何判断连接池是否实际被使用?写入数据库需要尽可能快,我担心版本 2 每次都必须重新建立与数据库的连接。这会破坏性能。如何衡量连接池是否正在发生以及它是否影响服务的吞吐量?
我一直在寻找有关此主题的 Deep Dive 资源,但我发现的大部分内容只是“在一个using
块中使用 SqlConnection,一切都会好起来的”。我正在寻找比这更深层次的解释。我真的很想了解这里发生的事情的本质,以便我寻找正确的性能问题。感谢您提供的任何见解。
解决方案
问题 1 可以通过与池相关的空闲超时来回答。
问题2:连接池默认设置为true,所以如果你没有在连接字符串中明确关闭它,你可以假设你正在使用它。我认为没有办法确定池中还剩下多少连接。如果您每次都使用完全相同的连接字符串,那么您可以放心地假设它们在同一个池中。
阅读此文档以更深入地了解连接池。
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling
您必须在 SQL Server 级别监视连接。
SELECT
DB_NAME(dbid) as DBName,
COUNT(dbid) as NumberOfConnections,
loginame as LoginName
FROM sys.sysprocesses
WHERE bid > 0
GROUP BY dbid, loginame;
推荐阅读
- android - 约束布局包装文本视图,但约束宽度太长而无法让其他视图可见
- ios - 如何使 UITextView 根据文本长度进行调整?
- python - 如何解决 Python 终端不解释 ANSI 转义序列的问题?
- css - 如何将形状从指向上更改为指向右
- excel - 连接字符串以在 VBA 中构建公式
- python - Python Tkinter askdirectory 在资源管理器中显示不正确的驱动器
- kotlin - 如何使用来自 firebase 的 dataCollection 创建微调器项目(在 Kotlin 中)
- python - 卡在python中的嵌套for循环中
- dolphindb - 在 DolphinDB 中使用 datehour() 函数的问题
- design-patterns - 如何从命令行参数建模全局状态?