当SqlTransaction被提交或回滚时,我想执行一些日志记录。我看到SqlTransaction类不会公开任何类似OnCommit或OnRollback的事件。
该死的!SqlTransaction类是密封的,我不能用继承来解决它。
现在,他们不允许这些事件发生的原因肯定是什么?
有没有一种方法可以用SqlTransaction或SqlTransaction的任何这样的替代品来完成这些事件呢?
谢谢。
发布于 2009-06-23 13:14:59
一种可能是创建一个实现IDbTransaction的类,并包装一个内部SqlTransaction。然后你必须说一些类似这样的话:
IDbCommand icommand = (IDbCommand)command; // Where command is a SqlCommand.
command.Transaction = itransaction; // Class implementing IDbTransaction and wrapping SqlTransaction.我还没有尝试过,上面的代码必须被认为是伪代码。我甚至怀疑它是否会起作用,但它可能值得一试。
发布于 2009-06-23 12:58:36
不是的。在SqlTransaction上没有内置的,在SqlCommand上也没有。
你能做的最好的就是用你自己的类来提供通知。
发布于 2012-07-15 21:01:37
在我们的系统中,我们对SqlTransaction使用了一个包装器。我认为它相当差劲,但它基本上是有效的。有关我们使用的完整类,请参见以下内容。实际上,这非常简单。
因为我们的所有方法现在都有一个CpoTransaction类型的事务参数,所以我们还添加了一个WrapTransaction静态函数,以便在常规CpoTransaction已经启动的情况下从常规事务中生成一个SqlTransaction。
请注意,在这些情况下,事务很可能是使用常规SqlTransaction提交/回滚的,并且事件将不会触发(因此必须求助于这样的解决方案是站不住脚的)。
/// <summary>
/// Provides a wrapper around an SqlTransaction that raises events on commit and rollback
/// </summary>
public partial class CpoTransaction : IDisposable {
private SqlTransaction mTransaction;
private bool mHasEnded;
public event EventHandler Committed, RolledBack;
/// <summary>
/// Provides a wrapper around an SqlTransaction that raises events on commit and rollback
/// </summary>
/// <param name="innerTransaction">The SqlTransaction to wrap</param>
internal CpoTransaction(SqlTransaction innerTransaction) {
mTransaction = innerTransaction;
mHasEnded = false;
}
/// <summary>
/// Rolls back the transaction from a pending state.
/// </summary>
internal void RollBack() {
if (!mHasEnded) {
mTransaction.Rollback();
OnRolledBack(this, new EventArgs());
mHasEnded = true;
} else
throw new InvalidOperationException("Transaction has already ended.");
}
/// <summary>
/// Commits the database transaction
/// </summary>
internal void Commit() {
if (!mHasEnded) {
mTransaction.Commit();
OnCommitted(this, new EventArgs());
mHasEnded = true;
} else
throw new InvalidOperationException("Transaction has already ended.");
}
/// <summary>
/// Add the SqlTransaction and its associated SqlConnection to the SqlCommand
/// </summary>
/// <param name="command">The command to add the SqlTransaction and SqlConnection to</param>
internal void SetTransaction(SqlCommand command) {
if (command == null)
throw new ArgumentNullException("command");
command.Connection = mTransaction.Connection;
command.Transaction = mTransaction;
}
/// <summary>
/// Gets whether or not the transaction has ended
/// </summary>
internal bool HasEnded {
get { return mHasEnded; }
}
/// <summary>
/// Gets the internal SqlConnection
/// </summary>
internal SqlConnection Connection {
get { return mTransaction.Connection; }
}
/// <summary>
/// Gets the internal SqlTransaction
/// </summary>
public SqlTransaction InnerTransaction {
get { return mTransaction; }
}
/// <summary>
/// Wraps an existing SqlTransaction into a CpoTransaction. IMPORTANT: See remarks!
/// </summary>
/// <param name="transaction">The transaction to wrap</param>
/// <returns>The SqlTransaction wrapped in a CpoTransaction</returns>
/// <remarks>
/// Use this method to allow CPO actions to be performed within the context of an already
/// existing transaction.
/// Note however that if the SqlTransaction is committed or rolled back without the use of the
/// CpoTransaction's Commit/Rollback functions, the events will not fire.
/// </remarks>
public static CpoTransaction WrapTransaction(SqlTransaction transaction) {
return new CpoTransaction(transaction);
}
/// <summary>
/// Disposes the SqlTransaction
/// </summary>
public void Dispose() {
mTransaction.Dispose();
if (!mHasEnded)
OnRolledBack(this, new EventArgs());
mHasEnded = true;
}
/// <summary>
/// Raises the Committed event
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">An EventArgs object containing event data</param>
protected void OnCommitted(object sender, EventArgs e) {
if (Committed != null)
Committed(sender, e);
Committed = null;
}
/// <summary>
/// Raises the RolledBack event
/// </summary>
/// <param name="sender">The sender of the event</param>
/// <param name="e">An EventArgs object containing event data</param>
protected void OnRolledBack(object sender, EventArgs e) {
if (RolledBack != null)
RolledBack(sender, e);
RolledBack = null;
}
}https://stackoverflow.com/questions/1032366
复制相似问题