一直很喜欢在方法头加个标签,实现方法体内自动事务,比如标签TransactionCallHandler,用到的AspectCore和SqlSugar均为开源,百度都可以找到GIT地址,最终达到的使用效果如下:
[TransactionCallHandler] public void Add(ArticleAct act, string username) { var article = new BasArticle() { CommentTimes = 0, Content = act.Content, Creater = username, CreateTime = DateTime.Now, ReadTimes = 0, Title = act.Title }; _basArticleRepository.Insert(article); }
方法上加个TransactionCallHandler头,则方法体内自动启用事务。
TransactionCallHandler代码:
public class TransactionCallHandlerAttribute : AbstractInterceptorAttribute { public async override Task Invoke(AspectContext context, AspectDelegate next) { var mySqlSugarClient = context.ServiceProvider.GetService<MySqlSugarClient>(); if (mySqlSugarClient.Ado.Transaction != null) { await next(context); return; } try { mySqlSugarClient.Ado.BeginTran(); await next(context); mySqlSugarClient.Ado.CommitTran(); } catch (Exception ex) { mySqlSugarClient.Ado.RollbackTran(); throw new Exception($"{ex.Message}{Environment.NewLine}{ex.Source}{Environment.NewLine}{ex.StackTrace}"); } } }
MySqlSugarClient是继承自SqlSugar,SqlSugarClient的类,内容:
using SqlSugar; using System; using System.Collections.Generic; using System.Text; using MyCore.Infrastructure.Dependency; namespace MyCore.Repositories.Common { public class MySqlSugarClient : SqlSugar.SqlSugarClient { private static ConnectionConfig config = new ConnectionConfig() { ConnectionString = "数据库链接字符串", DbType = DbType.MySql, InitKeyType = InitKeyType.Attribute, IsAutoCloseConnection = true }; public MySqlSugarClient() : base(config) { } } }
而仓储的实现举个文章的例子如下:
BasArticleRepository
using System; using System.Collections.Generic; using System.Text; using MyCore.Domain.Model; using MyCore.Domain.Repositories; using MyCore.Infrastructure; using MyCore.Infrastructure.Dependency; using MyCore.Repositories.Common; using SqlSugar; namespace MyCore.Repositories { public class BasArticleRepository : Repository<BasArticle> ,IBasArticleRepository { public BasArticleRepository(MySqlSugarClient context) : base(context) { } } }
Repository<T>部分代码如下:
public class Repository<T>: IDependency, IRepository<T> where T : class, new() { private static ILogger Log = Ioc.GetService<ILogger>(); private MySqlSugarClient _context; public Repository(MySqlSugarClient context) { this._context = context; //输出执行的语句 this._context.Aop.OnLogExecuting = (sql, pars) => { Log.Debug(sql + Environment.NewLine + Json.ToJson(pars) + Environment.NewLine); //Log.Debug(pars.) }; } public void BeginTran() { this._context.Ado.BeginTran(); } public void CommitTran() { this._context.Ado.CommitTran(); } public void RollbackTran() { this._context.Ado.RollbackTran(); } }
在Service服务层,直接使用构造函数注入,比如:
public class ArticleService:ApplicationBase,IArticleService { private readonly IBasArticleRepository _basArticleRepository; public ArticleService(IBasArticleRepository basArticleRepository) { _basArticleRepository = basArticleRepository; } }
对了,别忘记AOP是需要在startup.cs中ConfigureServices加入代码:
services.AddDynamicProxy(config => { config.Interceptors.AddTyped<ErrorLogHandler>(method => method.DeclaringType.Name.EndsWith("Service")); }); return services.BuildAspectCoreServiceProvider();
ErrorLogHandler是统一的错误日志处理,主要代码:
public class ErrorLogHandler: AbstractInterceptorAttribute { protected static ILogger Log = Ioc.GetService<ILogger>(); public async override Task Invoke(AspectContext context, AspectDelegate next) { try { await next(context); } catch (Exception ex) { //获取参数 Log.Error("传参:" + Json.ToJson(context.Parameters) + Environment.NewLine + ex + Environment.NewLine); throw ex; } } }