Oracle Managed DataAccess 连接对象保持连接打开
Oracle Managed DataAccess connection object is keeping the connection open
我正在使用 Oracle.ManagedDataAccess
Nuget 包版本 18.3.0
。我尝试了很多东西。我试图处理我能想到的所有东西,甚至是 oracle 参数对象。并将所有内容包装在 using
块中但无济于事。唯一真正对我有用的是注释行 OracleConnection.ClearPool(oracle);
。这是一个错误,还是一些与配置相关的问题,还是我误解了这里的内容?此外,我尝试删除 Oracle.ManagedDataAccess
的引用并将其替换为 System.Data.OracleClient
的引用,这实际上对我有用。它自动关闭了连接,因此没有连接处于 "In-Active" 状态。下面的代码我将它移到了一个简单的单个按钮中,Windows 表单应用程序可以 100% 确保没有任何干扰并且问题仍然存在。
using (var oracle = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))", new OracleCredential(userName,password)))
{
oracle.Open();
using (var command = new OracleCommand())
{
var query = "SELECT x from y where z=:param1";
command.Connection = oracle;
command.CommandText = query;
command.CommandType = System.Data.CommandType.Text;
var param1 = new OracleParameter(":param1", xyz);
command.Parameters.Add(param1);
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
//read the data from the reader
}
}
param1.Dispose();
}
//If this line is commented, there will be a connection left open, with InActive status
//OracleConnection.ClearPool(oracle);
}
password.Dispose();
return myData;
这是一张显示通过 Toad
打开的连接的图像。
当然,每次单击该按钮,上面的代码都会执行,并且新会话将保持打开状态,直到您在图像中看到。
名称 "TheTesterOfAllTests.exe" 是 Windows 表单应用程序。
这是配置问题吗?
除了使用 ClearPool
方法之外,还有什么方法可以解决这个问题吗?因为它会影响应用程序的性能。
P.S。最初使用上述代码的应用程序是一个被 Web 应用程序使用的 WCF Service
。
P.S。 2 存在某种内存泄漏,每次单击该按钮都会增加内存使用量
事实证明,问题出在 oracle 内部创建连接的方式上,因为对于每个新创建的 OracleConnection
对象,都会将一个新的连接添加到连接池中。我统计了连接池中的 91
个连接条目。
解决方案是为每个请求 "Per Request Scope" 使用一个 OracleConnection
实例。我通过使用一个简单的通用 IDatabase<TConnection>
接口和一个 TConnection GetConnection<TConnection>()
方法实现了这一点,当然对于将在同一请求实例上调用的每个方法,将进行一对 Open/Close 调用所以我们不会一直保持连接打开。
关于内存泄漏,我仍然无法 100%
证实这一点,但是当我使用 Oracle.DataAccess.Client
库而不是 Oracle.ManagedDataAccess
时,内存使用量急剧减少。所以,我切换回 Oracle.DataAccess.Client
.
P.S. 如果有关于这两个问题的新信息,我会更新这个答案,非常欢迎贡献,也许我对 Oracle 如何处理有一些误解与数据库连接。
我运行陷入同样的问题。
我通过更改 OracleConnection 的初始化解决了它。
来自
var con = new OracleConnection(
"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))",
new OracleCredential(userName,password));
到
var con = new OracleConnection(
"USER ID=myuser;PASSWORD=mypwd;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))");
对我来说,这种不同的行为看起来像是一个错误。
因此,我无法再使用 OracleCredential,必须将密码存储为字符串。这对我来说没问题。
我正在使用 Oracle.ManagedDataAccess
Nuget 包版本 18.3.0
。我尝试了很多东西。我试图处理我能想到的所有东西,甚至是 oracle 参数对象。并将所有内容包装在 using
块中但无济于事。唯一真正对我有用的是注释行 OracleConnection.ClearPool(oracle);
。这是一个错误,还是一些与配置相关的问题,还是我误解了这里的内容?此外,我尝试删除 Oracle.ManagedDataAccess
的引用并将其替换为 System.Data.OracleClient
的引用,这实际上对我有用。它自动关闭了连接,因此没有连接处于 "In-Active" 状态。下面的代码我将它移到了一个简单的单个按钮中,Windows 表单应用程序可以 100% 确保没有任何干扰并且问题仍然存在。
using (var oracle = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))", new OracleCredential(userName,password)))
{
oracle.Open();
using (var command = new OracleCommand())
{
var query = "SELECT x from y where z=:param1";
command.Connection = oracle;
command.CommandText = query;
command.CommandType = System.Data.CommandType.Text;
var param1 = new OracleParameter(":param1", xyz);
command.Parameters.Add(param1);
using (var reader = command.ExecuteReader())
{
if (reader.Read())
{
//read the data from the reader
}
}
param1.Dispose();
}
//If this line is commented, there will be a connection left open, with InActive status
//OracleConnection.ClearPool(oracle);
}
password.Dispose();
return myData;
这是一张显示通过 Toad
打开的连接的图像。
这是配置问题吗?
除了使用 ClearPool
方法之外,还有什么方法可以解决这个问题吗?因为它会影响应用程序的性能。
P.S。最初使用上述代码的应用程序是一个被 Web 应用程序使用的 WCF Service
。
P.S。 2 存在某种内存泄漏,每次单击该按钮都会增加内存使用量
事实证明,问题出在 oracle 内部创建连接的方式上,因为对于每个新创建的 OracleConnection
对象,都会将一个新的连接添加到连接池中。我统计了连接池中的 91
个连接条目。
解决方案是为每个请求 "Per Request Scope" 使用一个 OracleConnection
实例。我通过使用一个简单的通用 IDatabase<TConnection>
接口和一个 TConnection GetConnection<TConnection>()
方法实现了这一点,当然对于将在同一请求实例上调用的每个方法,将进行一对 Open/Close 调用所以我们不会一直保持连接打开。
关于内存泄漏,我仍然无法 100%
证实这一点,但是当我使用 Oracle.DataAccess.Client
库而不是 Oracle.ManagedDataAccess
时,内存使用量急剧减少。所以,我切换回 Oracle.DataAccess.Client
.
P.S. 如果有关于这两个问题的新信息,我会更新这个答案,非常欢迎贡献,也许我对 Oracle 如何处理有一些误解与数据库连接。
我运行陷入同样的问题。 我通过更改 OracleConnection 的初始化解决了它。
来自
var con = new OracleConnection(
"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))",
new OracleCredential(userName,password));
到
var con = new OracleConnection(
"USER ID=myuser;PASSWORD=mypwd;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=myhost)(PORT=SomePortHere))(CONNECT_DATA=(SERVER=SHARED)(SERVICE_NAME=anotherHost)))");
对我来说,这种不同的行为看起来像是一个错误。
因此,我无法再使用 OracleCredential,必须将密码存储为字符串。这对我来说没问题。