所以,我还没有看到从这个方向谈论这个问题的帖子。
我正在尝试编写一些代码来跟踪打开与数据库的 odbc 连接所需的平均时间。
我认为这很简单。 创建连接,秒表.启动,打开连接,秒表.关闭。
我发现,即使我在连接字符串中将池设置为 no,第一个连接也需要 700 毫秒左右,并且同一应用程序执行中的所有后续尝试都报告 0 毫秒。
我计划让一个监视器服务在计时器上运行它,但如果我在第一次尝试后没有获得“真正的”连接,那就毫无意义了。
每次打开花费的时间不应该几乎相同吗? 为什么第一次尝试后结果是0?
工作人员服务中的简单示例(我摆脱了使用包装器并尝试显式关闭/处置,但似乎并不重要。我最初有 Pooling=False 并认为这也是问题所在,但似乎没有任何改变行为):
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
}
string connectionString = $"Driver={{ODBC Driver 17 for SQL Server}};Server=blah;Database=blah;UID=blah;PWD=blah;Pooling=No";
Stopwatch stopwatch = new Stopwatch();
OdbcConnection connection = new OdbcConnection(connectionString);
stopwatch.Start();
connection.Open();
stopwatch.Stop();
connection.Close();
connection.Dispose();
connection = null;
Console.WriteLine($"Time taken to open the connection: {stopwatch.ElapsedMilliseconds} ms");
Console.ReadKey();
}
}
有人知道为什么要这样做和/或如何使其明确不重用连接吗?
所以我正在寻找同样的东西,发现它并不像使用 ADO.NET 驱动程序那么容易(比如在连接字符串中定义它)。
我找到了以下选项,其中只有选项 1 适用于我的情况(使用 “IBM i Access ODBC 驱动程序”):
odbcad32.exe
并转到“连接池”选项卡。双击驱动程序并停用该驱动程序的池化。这有一个缺点 - 此设置会停用该客户端上所有应用程序的池化。我想出的解决方法是复制驱动程序的注册表项(位于 Computer\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI
- 或者您可以使用命令 odbcconf /A {INSTALLDRIVER "<NEW_DRIVER_NAME>|driver=<DLL_PATH>"}
,但您可能必须提供其他设置),将其重命名为其他名称并更改连接这个“新”驱动程序上的池设置。因此,您只能针对此应用程序停用它。问题是这不完全是一个便携式解决方案。Pooling=false
添加到连接字符串。 (在我的情况下不起作用,也许驱动程序可以决定是否实施它)SQLSetEnvAttr
调用方法 odbc32.dll
。我使用了如下代码。常量的值来自 sqlext.h。 (就我而言,该函数返回 0
作为响应,但没有任何效果。)[DllImport("odbc32.dll")]
private static extern int SQLSetEnvAttr(IntPtr EnvironmentHandle, int Attribute, IntPtr ValuePtr, int StringLength);
private const int SQL_ATTR_CONNECTION_POOLING = 201;
private const int SQL_CP_OFF = 0;
// Disable connection pooling
var r = SQLSetEnvAttr(IntPtr.Zero, SQL_ATTR_CONNECTION_POOLING, new IntPtr(SQL_CP_OFF), 0);