複数のビジネス オブジェクトが単一のトランザクション内でデータベースに保存できるように、接続オブジェクトを渡す必要があることに気付きました。
各ビジネス オブジェクトがデータベースへの独自の SQLConnection を作成する必要がある場合、トランザクションは分散トランザクションにエスカレートするので、それは避けたかったのです。
オブジェクトを保存するために SQLConnection オブジェクトをパラメータとして渡さなければならないのは好きではなかったので、SQLConnection オブジェクトの作成、SQLConnection オブジェクトの使用状況の追跡、および使用されていないときの SQLConnection オブジェクトの切断を処理する ConnectionManager を作成しました。
以下は、ConnectionManager の例としてのコードです。
public class ConnectionManager: IDisposable
{
private ConnectionManager instance;
[ThreadStatic]
private static object lockObject;
private static Object LockObject
{
get
{
if (lockObject == null)
lockObject = new object();
return lockObject;
}
}
[ThreadStatic]
private static Dictionary<string, ConnectionManager> managers;
private static Dictionary<string, ConnectionManager> Managers
{
get
{
if (managers == null)
managers = new Dictionary<string, ConnectionManager>();
return managers;
}
}
private SqlConnection connection = null;
private int referenceCount;
private string name;
public static ConnectionManager GetManager(string connectionName)
{
lock (LockObject)
{
ConnectionManager mgr;
if (Managers.ContainsKey(connectionName))
{
mgr = Managers[connectionName];
}
else
{
mgr = new ConnectionManager(connectionName);
Managers.Add(connectionName, mgr);
}
mgr.AddRef();
return mgr;
}
}
private ConnectionManager(string connectionName)
{
name = connectionName;
connection = new SqlConnection(GetConnectionString(connectionName));
connection.Open();
}
private string GetConnectionString(string connectionName)
{
string conString = Configuration.ConnectionString;
return conString;
}
public SqlConnection Connection
{
get { return connection; }
}
private void AddRef()
{
referenceCount += 1;
}
private void DeRef()
{
lock (LockObject)
{
referenceCount -= 1;
if (referenceCount == 0)
{
connection.Dispose();
Managers.Remove(name);
}
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
DeRef();
}
}
~ConnectionManager()
{
Dispose(false);
}
#endregion
}
ビジネスオブジェクトからそれを使用する方法は次のとおりです。
public void Save()
{
using (ConnectionManager mrg = ConnectionManager.GetManager("SQLConnectionString")
{
using (SQLCommand cmd = new SQLCommand)
{
cmd.connection = mgr.Connection
// More ADO Code Here
}
_childObject.Save(); //this child object follows the same pattern with a using ConnectionManager.
}
}
ビジネス オブジェクトを保存すると、そのすべての子も同じ接続オブジェクトを使用して保存されます。スコープが元の親から離れると、using ステートメントは接続を閉じます。
これは、CSLA フレームワークで Rocky Lhotka から学んだパターンです。
キース