Möchte man über mehrere typisierte TableAdapter eine Transaction abbilden ohne dafür jeden TableAdapter partiel zu erweitern sollte dieses Snippet weiterhelfen.
Diesem Transactionsmanager werden die für eine Transaction benötigten Adapter bekanntgegeben und die Transactionsbefehle gesteuert.
public class TransactionManager
{
private SqlConnection _connection;
private List<object> _adapters;
private SqlTransaction _transaction;
public SqlTransaction Transaction
{
get { return this._transaction; }
set { this._transaction = value;}
}
//Konstruktor
public TransactionManager() { _adapters = new List<object>(); }
/// <summary>
/// Hier kann ein Adapter registriert werden.
/// </summary>
/// <param name="adapter"></param>
public void registerAdapter(object adapter)
{
// suche Connection
PropertyInfo conn = adapter.GetType().GetProperty("Connection", BindingFlags.Instance | BindingFlags.NonPublic);
if (this._connection == null)
_connection = conn.GetValue(adapter, null) as SqlConnection;
else
conn.SetValue(adapter, _connection, null);
_adapters.Add(adapter);
}
public void registerAdapter(object[] adapters)
{
foreach (object a in adapters)
this.registerAdapter(a);
}
public void BeginTransaction()
{
if (this._connection == null)
throw new Exception("no Adapter registered");
if (this._connection.State != ConnectionState.Open) this._connection.Open();
// Create the transaction and assign it to the Transaction property
this.Transaction = this._connection.BeginTransaction();
// set the Transaction for the others too
foreach (object curAdapter in _adapters)
{
PropertyInfo adapterProp = curAdapter.GetType().GetProperty("Adapter", BindingFlags.Instance | BindingFlags.NonPublic);
SqlDataAdapter dataAdapter = adapterProp.GetValue(curAdapter, null) as SqlDataAdapter;
if (dataAdapter.InsertCommand != null)
dataAdapter.InsertCommand.Transaction = this.Transaction;
if (dataAdapter.UpdateCommand != null)
dataAdapter.UpdateCommand.Transaction = this.Transaction;
if (dataAdapter.DeleteCommand != null)
dataAdapter.DeleteCommand.Transaction = this.Transaction;
PropertyInfo commandCollProp = curAdapter.GetType().GetProperty("CommandCollection", BindingFlags.Instance | BindingFlags.NonPublic);
SqlCommand[] commandCollection = commandCollProp.GetValue(curAdapter, null) as SqlCommand[];
foreach (SqlCommand command in commandCollection)
{
command.Transaction = this.Transaction;
}
}
}
public void Comit()
{
this.Transaction.Commit();
this._connection.Close();
}
public void Rollback()
{
this.Transaction.Rollback();
this._connection.Close();
}
}
// möglicher Aufruf
TransactionManager transactionManager = new TransactionManager();
transactionManager.registerAdapter(new object[] { ua, cA, ceA });
transactionManager.BeginTransaction();
try{
// do something
ua.dosomething();
cA.dosomething();
transactionManager.Comit();
}
catch
{
transactionManager.Rollback();
throw;
}
Kommentare zum Snippet