AOP(面向切麵編程),通過預編譯方式和運行期間動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。 AspectCore 提供了一個 ...
AOP(面向切麵編程),通過預編譯方式和運行期間動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
AspectCore 提供了一個全新的輕量級和模塊化的Aop解決方案,現在已經支持Asp.Net Core。
實現AOP類TransactionalAttribute:
1 /// <summary> 2 /// 為工作單元提供事務一致性 3 /// </summary> 4 public class TransactionalAttribute : AbstractInterceptorAttribute 5 { 6 IUnitOfWork _unitOfWork { get; set; } 7 8 public async override Task Invoke(AspectContext context, AspectDelegate next) 9 { 10 try 11 { 12 _unitOfWork = context.ServiceProvider.GetService(typeof(IUnitOfWork)) as IUnitOfWork; 13 _unitOfWork.BeginTransaction(); 14 await next(context); 15 _unitOfWork.Commit(); 16 } 17 catch (Exception) 18 { 19 _unitOfWork.Rollback(); 20 throw; 21 } 22 } 23 }
這裡需要引用AspectCore.Abstractions.dll庫,代碼中的UnitOfWork類在前面的文章中有講解:.NetCore學習筆記:一、UnitOfWork工作單元。
在讀寫資料庫的時候,將_unitOfWork.DbTransaction加入。下麵這個是Dapper的Execute實例:
_unitOfWork.DbConnection.Execute(sql, param: param, transaction: _unitOfWork.DbTransaction, commandType: commandType);
為Web應用程式添加配置:
1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 CreateHostBuilder(args).Build().Run(); 6 } 7 8 public static IHostBuilder CreateHostBuilder(string[] args) => 9 Host.CreateDefaultBuilder(args) 10 .ConfigureWebHostDefaults(webBuilder => 11 { 12 webBuilder.UseStartup<Startup>(); 13 }) 14 .UseDynamicProxy();//aspcectcore 15 }
在netcore3.1中配置比較簡單,只需要在Program類中添加UseDynamicProxy()就可以了。
這樣在需要用到事務的地方我們使用[Transactional]標註一下就可以了。
1 public class TestService : ITestService 2 { 3 ITestDomain _testDomain { get; set; } 4 public TestService(ITestDomain testDomain) 5 { 6 this._testDomain = testDomain; 7 } 8 9 public Test Get(string id) 10 { 11 var test = _testDomain.Get(id); 12 return test; 13 } 14 15 [Transactional] 16 public void Insert(List<Test> list) 17 { 18 _testDomain.InsertList(list); 19 } 20 }
上段代碼中的ITestDomain實現:
public class TestDomain : ITestDomain { IRepository<Test> _testRepository { get; set; } public TestDomain(IRepository<Test> testRepository) { this._testRepository = testRepository; } public Test Get(string id) { return _testRepository.Get(id); } public void Insert(List<Test> list) { if (list == null) return; foreach(var item in list) _testRepository.Insert(item); } }
代碼片段中的Repository在前面的文章中有講解:.NetCore學習筆記:二、基於Dapper的泛型Repository。
這樣就實現AOP事務了。