Mat*_*att 4 c# sql database enterprise-library executescalar
静态类中的以下方法给出了超时异常,因为连接池被最大化.
在调试模式下,我查看了sql Management studio,看到有150个睡眠进程.
我期望连接自动关闭...我也试过把它作为一个静态成员,但仍然有相同的错误.
有任何想法吗?继承人代码:
public static Decimal ExecuteScalarDec(string procName, params object[] parameters)
{
try
{
return (Decimal)DatabaseFactory.CreateDatabase().ExecuteScalar(procName, parameters);
}
catch (Exception ex)
{
throw new Exception(procName.ToString() + " " + parameters.ToString(), ex);
}
}
Run Code Online (Sandbox Code Playgroud)
"按照设计,大多数Database类方法在每次调用时都会处理数据库连接的打开和关闭.因此,应用程序代码不需要包含用于管理连接的代码." ExecuteReader是一个例外(因为它返回一个资源).ExecuteScalar处于不确定状态:它返回一个'标量'.但是,我猜标量可能很重,例如.从大型数据类型返回构造的流,这将需要保持打开的连接. - Remus Rusanu
我无法评论你的答案,因为它说"评论需要50个声誉"我注册了我的用户后......
我在executeScalar()中返回一个列Id并且返回了值 - 我知道这是因为下一次执行标量的调用仅在我收到一个值后被调用...它不会理解为流将是永远保持开放我在sql Management中看到所有进程都在休眠.
public static Decimal ExecuteScalarDec(string procName, params object[] parameters)
{
try
{
using (Database database = DatabaseFactory.CreateDatabase())
{
return (Decimal)database.ExecuteScalar(procName, parameters);
}
}
catch (Exception ex)
{
throw new Exception(procName.ToString() + " " + parameters.ToString(), ex);
}
}
Run Code Online (Sandbox Code Playgroud)
更新
好的,因为这是EnterpriseLibrary代码.该数据库类实现ExecuetScalar这样的(其他签名会崩溃到这最终):
public virtual object ExecuteScalar(DbCommand command)
{
if (command == null) throw new ArgumentNullException("command");
using (ConnectionWrapper wrapper = GetOpenConnection())
{
PrepareCommand(command, wrapper.Connection);
return DoExecuteScalar(command);
}
}
Run Code Online (Sandbox Code Playgroud)
并且ConnectionWrapper处理连接(链接中的源文件的结尾),理论上,你的调用应该没问题并且处理连接.
GetOpenConnection()方法返回一个处理连接的包装器...除非当前存在一个连接TransactionScopeConnections:
protected ConnectionWrapper GetOpenConnection(bool disposeInnerConnection)
{
DbConnection connection = TransactionScopeConnections.GetConnection(this);
if (connection != null)
{
return new ConnectionWrapper(connection, false);
}
return new ConnectionWrapper(GetNewOpenConnection(), disposeInnerConnection);
}
Run Code Online (Sandbox Code Playgroud)
以下是TransactionScopeConnections返回连接的方法:
public static DbConnection GetConnection(Database db)
{
Transaction currentTransaction = Transaction.Current;
if (currentTransaction == null)
return null;
Dictionary<string, DbConnection> connectionList;
DbConnection connection;
lock (transactionConnections)
{
if (!transactionConnections.TryGetValue(currentTransaction, out connectionList))
{
// We don't have a list for this transaction, so create a new one
connectionList = new Dictionary<string, DbConnection>();
transactionConnections.Add(currentTransaction, connectionList);
// We need to know when this previously unknown transaction is completed too
currentTransaction.TransactionCompleted += OnTransactionCompleted;
}
}
lock (connectionList)
{
// Next we'll see if there is already a connection. If not, we'll create a new connection and add it
// to the transaction's list of connections.
// This collection should only be modified by the thread where the transaction scope was created
// while the transaction scope is active.
// However there's no documentation to confirm this, so we err on the safe side and lock.
if (!connectionList.TryGetValue(db.ConnectionString, out connection))
{
// we're betting the cost of acquiring a new finer-grained lock is less than
// that of opening a new connection, and besides this allows threads to work in parallel
connection = db.GetNewOpenConnection();
connectionList.Add(db.ConnectionString, connection);
}
}
return connection;
}
Run Code Online (Sandbox Code Playgroud)
现在除非我弄错了,否则TransactionsScopeConnections它将始终为一个全新的数据库对象(如你的情况)创建一个新的联系,并将它们保存在内部字典中.Database对象没有实现Disposable,所以我在确定应该从这个TransactionScopeConnecitons内部列表中清除连接的确切位置时丢失了.
Matt,是否可以按照本文中有关CLR泄漏的步骤进行操作,并查看流程中是否有大量的Database对象?加载SOS并执行操作!dumpheap -type Microsoft.Practices.EnterpriseLibrary.Data.Database.如果你发现很多物体,你可以跟踪其中一些物体上的引脚堆栈!gcroot <AddressOfObject>