如何创建方面装饰器来处理 EF 事务

How to create an aspect decorator to handle EF transactions

我正在(维护)一个充当数据访问层的 dll 程序集,有许多方法需要事务处理,许多其他方法不需要,它目前是一个 "functional" dll,没有任何事务处理方法,我需要添加它,所以我正在寻找一种简单的方法来添加事务处理程序。

我想知道是否可以使用 AOP 创建装饰器,我可以将其添加到需要事务的方法中。

我想要这样的东西:

[Transaction]
void MyDbMethod()
{
  //DoSomething
  myContext.SaveChanges();  
}

我使用 Code First 的 EF 模型定义,当前项目使用 Unity 框架来处理其他一些 DI 任务,可以使用该框架吗?

如果有人遇到同样的问题,我没有找到任何 "by hand" 解决方案,而是使用 PostSharp 库及其 OnMethodBoundaryAspect class,但请注意,目前 free/express 许可证对您可以使用它的 class 数量有限制,因此请仔细阅读其限制。

using System.Transactions;
using PostSharp.Aspects;
using PostSharp.Serialization;

namespace MyProject
{
    [PSerializable]
    public class Transaction : OnMethodBoundaryAspect
    {
        public Transaction()
        {
            //Required if the decorated method is async
            ApplyToStateMachine = true;
        }

        public override void OnEntry(MethodExecutionArgs args)
        {
            //TransactionScopeAsyncFlowOption.Enabled => Required if the decorated method is async
            var transactionScope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled);
            args.MethodExecutionTag = transactionScope;
        }

        public override void OnSuccess(MethodExecutionArgs args)
        {
            var transactionScope = (TransactionScope)args.MethodExecutionTag;
            transactionScope.Complete();
        }

        public override void OnExit(MethodExecutionArgs args)
        {
            var transactionScope = (TransactionScope)args.MethodExecutionTag;
            transactionScope.Dispose();
        }
    }
}

您可以使用 NConcern .NET AOP Framework

这是一个开源运行时 AOP 框架,我积极致力于此。

public class DataAccessLayer : IAspect
{
    public IEnumerable<IAdvice> Advise(MethodInfo method)
    {
        //define how to rewrite method
        yield return Advice.Basic.Arround(invoke =>
        {
            using (var transaction = new TransactionScope(...))
            {
                invoke(); //invoke original code
                transaction.Complete();
            }
        });
    }
}

您的公司

public class MyBusiness
{
    [Transaction]
    void MyDbMethod()
    {
    }
}

将交易范围方面附加到您的业务

Aspect.Weave<DataAccessLayer>(method => method.IsDefined(typeof(TransactionAttribute), true);