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は接続(リンク内のソースファイルの終わり)を破棄するので、理論は進みます。呼び出しはOKであり、接続を破棄する必要があります。
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オブジェクトはDisposableを実装していないため、このTransactionScopeConnecitons
内部リストから接続をクリーンアップするのは誰であるかを正確に判断できません。
マット、 CLRリークに関するこの記事の手順に従って、プロセスに多数のデータベースオブジェクトがあるかどうかを確認することは可能ですか?SOSをロードし、を実行し!dumpheap -type Microsoft.Practices.EnterpriseLibrary.Data.Database
ます。多くのオブジェクトを見つけた場合、それらのいくつかのピンスタックをトレースできますか?!gcroot <AddressOfObject>