【问题标题】:How to create an aspect decorator to handle EF transactions如何创建方面装饰器来处理 EF 事务
【发布时间】:2016-12-28 14:43:15
【问题描述】:

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

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

我想要这样的东西:

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

对于我使用 Code First 的 EF 模型定义,当前项目使用 Unity 框架执行其他一些 DI 任务,该框架可以用于此吗?

【问题讨论】:

标签: c# entity-framework unity-container aop


【解决方案1】:

如果有人遇到同样的问题,我没有找到任何“手动”解决方案,而是使用了 PostSharp 库及其 OnMethodBoundaryAspect 类,但要小心,此时免费/express 许可证对您可以使用的类数量有限制,因此请仔细阅读其限制。

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();
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以使用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);
    

    【讨论】:

    • 不知道这个项目,似乎是 postsharp 和 fody 的一个不错的“入门”替代品。该页面提到它在运行时执行编织;与编译时编织或使用 Cecil 摆弄二进制文件相比,这对性能有何影响?
    • 性能主要在“点火时间”而不是标称时间中改变。在我自己的基准测试中,它可以比 PostSharp 在名义上使用更快。
    • 很好听;我一直在寻找类似的东西,因为 Postsharp 非常昂贵,而且 Fody 的扩展质量非常不稳定。感谢您抽出宝贵时间在这里发帖! :)
    • 不客气,如果需要或者只是如果有什么不清楚的地方,请随时给我反馈以改进框架......就像我说的,我在这个项目上一直很活跃。
    猜你喜欢
    • 2012-08-02
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2016-11-03
    • 2021-06-22
    • 2021-11-14
    • 1970-01-01
    • 2014-02-13
    相关资源
    最近更新 更多