一直很喜欢在方法头加个标签,实现方法体内自动事务,比如标签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;
}
}
}