如何避免重写相同的 using 语句?

How to avoid rewriting identical using statements?

有没有办法在 Disposable 对象中创建嵌套使用,所以此代码:

using (var ctx = new MyEntities())
{
    ctx.Connection.Open();
    using (var tx = dbContext.Connection.BeginTransaction())
    {
        // ... do awesome things here

        ctx.SaveChanges();
        tx.Commit();
    }
}

像这样:

using (var txContext = new TransactionContext())
{
    // ... do awesome things here
}

?

目前我有:

public class TransactionContext : IDisposable
{
    private MyEntities DbContext { get; set; }
    private DbTransaction Transaction { get; set; }

    public TransactionContext()
    {
        DbContext = new MyEntities();
        DbContext.Connection.Open();

        Transaction = DbContext.Connection.BeginTransaction();
    }

    void IDisposable.Dispose()
    {
        try
        {
            DbContext.SaveChanges();
            Transaction.Commit();
        }
        catch (Exception exception)
        {
            Transaction.Rollback();
            DbContext.Dispose();
        }
    }
}

我不确定处理不同 Disposables 的方式是否正确,尤其是在 error/exception.

的情况下

为此使用方法而不是 class 可能会更好。

private static void RunInTransaction(Action<MyEntities, DbTransaction> action)
{
    using (var ctx = new MyEntities())
    {
        ctx.Connection.Open();
        using (var tx = ctx.Connection.BeginTransaction())
        {
            action(ctx, tx);
            ctx.SaveChanges();
            tx.Commit();
        }
    }
}

那你就可以这样调用了

RunInTransaction((ctx,tx) => 
{
    // ... do awesome things here
}); 

您还可以创建一个 returns 值

的版本
private static T RunInTransactionAndReturn<T>(
    Func<MyEntities, DbTransaction, T> function)
{
    using (var ctx = new MyEntities())
    {
        ctx.Connection.Open();
        using (var tx = ctx.Connection.BeginTransaction())
        {
            var result = function(ctx, tx);
            ctx.SaveChanges();
            tx.Commit();
            return result;
        }
    }
}

那你就可以这样调用了

var result = RunInTransactionAndReturn((ctx,tx) => 
{
    // ... do awesome things here
    return someResult;
});