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()メソッドは、1が現在の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
は(あなたの場合のように)常に新しいデータベースオブジェクトの新鮮な賛辞を作成し、内部の辞書に保持します。データベースオブジェクトはDisposableを実装していないので、このTransactionScopeConnecitons
内部リストから接続をクリーンアップすることになっている人を正確に特定することはできません。
マットは、this article about CLR leaksの手順を実行して、プロセスに多数のデータベースオブジェクトがあるかどうかを確認することは可能ですか?SOSをロードし、!dumpheap -type Microsoft.Practices.EnterpriseLibrary.Data.Database
を実行してください。多くのオブジェクトが見つかった場合は、一部のピンスタックをトレースできますか?!gcroot <AddressOfObject>
ExecuteScalar()メソッドは、基になるDbConnectionオブジェクトと何をするのですか?Dispose()またはClose()を呼び出しますか? "using"ステートメント? –