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);
}
}
更新
OK,因爲這是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
將始終爲全新的數據庫對象(如您的情況)創建一個新的連接並將它們保存在內部字典中。數據庫對象沒有實現一次性,所以我迷失在確定誰應該清理這個TransactionScopeConnecitons
內部列表中的連接。
Matt,是否可以按照this article about CLR leaks中的步驟操作並查看過程中是否有大量數據庫對象?加載SOS並執行!dumpheap -type Microsoft.Practices.EnterpriseLibrary.Data.Database
。如果你發現許多對象,你能跟蹤其中的一些針堆棧嗎?!gcroot <AddressOfObject>
ExecuteScalar()方法是如何處理底層DbConnection對象的 - 它調用Dispose()或Close()方法,例如通過使用一個「使用」聲明? – 2009-07-23 06:29:03