首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#?SqlTransaction暴露事件的替代方案?

C#?SqlTransaction暴露事件的替代方案?
EN

Stack Overflow用户
提问于 2009-06-23 12:49:42
回答 3查看 817关注 0票数 1

当SqlTransaction被提交或回滚时,我想执行一些日志记录。我看到SqlTransaction类不会公开任何类似OnCommit或OnRollback的事件。

该死的!SqlTransaction类是密封的,我不能用继承来解决它。

现在,他们不允许这些事件发生的原因肯定是什么?

有没有一种方法可以用SqlTransaction或SqlTransaction的任何这样的替代品来完成这些事件呢?

谢谢。

EN

回答 3

Stack Overflow用户

发布于 2009-06-23 13:14:59

一种可能是创建一个实现IDbTransaction的类,并包装一个内部SqlTransaction。然后你必须说一些类似这样的话:

代码语言:javascript
复制
IDbCommand icommand = (IDbCommand)command; // Where command is a SqlCommand.
command.Transaction = itransaction; // Class implementing IDbTransaction and wrapping SqlTransaction.

我还没有尝试过,上面的代码必须被认为是伪代码。我甚至怀疑它是否会起作用,但它可能值得一试。

票数 1
EN

Stack Overflow用户

发布于 2009-06-23 12:58:36

不是的。在SqlTransaction上没有内置的,在SqlCommand上也没有。

你能做的最好的就是用你自己的类来提供通知。

票数 0
EN

Stack Overflow用户

发布于 2012-07-15 21:01:37

在我们的系统中,我们对SqlTransaction使用了一个包装器。我认为它相当差劲,但它基本上是有效的。有关我们使用的完整类,请参见以下内容。实际上,这非常简单。

因为我们的所有方法现在都有一个CpoTransaction类型的事务参数,所以我们还添加了一个WrapTransaction静态函数,以便在常规CpoTransaction已经启动的情况下从常规事务中生成一个SqlTransaction。

请注意,在这些情况下,事务很可能是使用常规SqlTransaction提交/回滚的,并且事件将不会触发(因此必须求助于这样的解决方案是站不住脚的)。

代码语言:javascript
复制
/// <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;
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1032366

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档