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);
}
}
更新
好的,因为这是 EnterpriseLibrary 代码。Database类像这样实现 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);
}
}
并且 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);
}
以下是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;
}
现在,除非我弄错了,否则TransactionsScopeConnections
将始终为全新的 Database 对象(如您的情况)创建一个新的连接,并将它们保存在内部字典中。Database 对象没有实现 Disposable,所以我无法确定到底应该由谁来清理这个TransactionScopeConnecitons
内部列表中的连接。
马特,是否可以按照本文中有关 CLR 泄漏的步骤,查看您的进程中是否存在大量数据库对象?加载 SOS 并执行!dumpheap -type Microsoft.Practices.EnterpriseLibrary.Data.Database
. 如果你发现很多物体,你能用!gcroot <AddressOfObject>