创建仓储
首先需要建仓储接口层和仓储实现层
泛型仓储类如下(后续需要单独注入一次泛型仓储)
using IRepository;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SqlSugar;
namespace Repository
{
/// <summary>
/// 父仓储类
/// </summary>
/// <typeparam name="T"></typeparam>
public class BaseRepository<T> : SimpleClient<T>, IBaseRepository<T> where T : class, new()
{
/// <summary>
/// 日志组件
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// 无日志构造函数(不需要SQL日志选这个)
/// </summary>
/// <param name="context"></param>
public BaseRepository(ISqlSugarClient context) : base(context)
{
}
/// <summary>
/// 有日志构造函数(需要打印SQL选这个)
/// </summary>
/// <param name="context"></param>
/// <param name="logger"></param>
public BaseRepository(ISqlSugarClient context, ILogger logger) : base(context)
{
base.Context = context;
_logger = logger;
base.Context.Aop.OnLogExecuting = (sql, pars) =>
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
foreach (var row in pars)
{
Dictionary<string, object> value = new Dictionary<string, object>();
value.Add(row.ParameterName, row.Value);
result.Add(value);
}
_logger.LogCritical("\r\n 【开始打印仓储日志】:\r\n 【执行时间】:{0} \r\n 【SQL执行语句】:{1} \r\n 【参数】:{2}", DateTime.Now.ToString(), sql, JsonConvert.SerializeObject(result));
};
// SQL执行完
base.Context.Aop.OnLogExecuted = (sql, pars) =>
{
_logger.LogCritical("\r\n 【结束打印仓储日志】:\r\n 【执行时间】:{0} \r\n 【SQL执行时间】:{1}", DateTime.Now.ToString(), base.Context.Ado.SqlExecutionTime.ToString());
};
}
/// <summary>
/// 分页方法(公共方法)
/// </summary>
/// <param name="PageNow">当前页</param>
/// <param name="PageSize">每页个数</param>
/// <returns></returns>
public List<T> ToPageList(int PageNow, int PageSize)
{
return base.Context.Queryable<T>().Skip(PageSize * (PageNow - 1)).Take(PageSize).ToList();
}
}
}
在这里把SqlSugarClient拿到了,并且继承了仓储接口,和官方文档有所差异
using IRepository.DI;
using SqlSugar;
namespace IRepository
{
/// <summary>
/// 父仓储接口
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IBaseRepository<T> : ISimpleClient<T>, IScoped where T : class, new()
{
/// <summary>
/// 分页方法(公共方法)
/// </summary>
/// <param name="PageNow">当前页</param>
/// <param name="PageSize">每页个数</param>
/// <returns></returns>
List<T> ToPageList(int PageNow, int PageSize);
}
}
注入仓储
继承IScoped接口完成自动注入
同样需要一个单独的注入方法,根据命名空间来注入对应的接口和类
public static IServiceCollection AddRepository(this IServiceCollection services)
{
// 注入泛型仓储
services.AddScoped(typeof(Repository.BaseRepository<>));
var singletonType = typeof(IRepository.DI.ISingleton); // 单例
var transientType = typeof(IRepository.DI.ITransient); // 瞬时
var scopedType = typeof(IRepository.DI.IScoped); // 作用域
// 获取实现了三个生命周期接口的程序集
var allTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t =>
t.GetInterfaces().Contains(transientType) ||
t.GetInterfaces().Contains(singletonType) ||
t.GetInterfaces().Contains(scopedType)));
// class的程序集
var implementTypes = allTypes.Where(x => x.IsClass).ToArray();
// 接口的程序集
var interfaceTypes = allTypes.Where(x => x.IsInterface).ToArray();
foreach (var implementType in implementTypes)
{
var interfaceType = interfaceTypes.FirstOrDefault(x => x.IsAssignableFrom(implementType));
// class有接口,用接口注入
if (interfaceType != null)
{
// 判断用什么方式注入
if (interfaceType.GetInterfaces().Contains(singletonType))
{
// 单例
services.AddSingleton(interfaceType, implementType);
}
else if (interfaceType.GetInterfaces().Contains(transientType))
{
// 瞬时
services.AddTransient(interfaceType, implementType);
}
else if (interfaceType.GetInterfaces().Contains(scopedType))
{
// 作用域
services.AddScoped(interfaceType, implementType);
}
}
else // class没有接口,直接注入class
{
// 判断用什么方式注入
if (implementType.GetInterfaces().Contains(singletonType))
{
// 单例
services.AddSingleton(implementType);
}
else if (implementType.GetInterfaces().Contains(transientType))
{
// 瞬时
services.AddTransient(implementType);
}
else if (implementType.GetInterfaces().Contains(scopedType))
{
// 作用域
services.AddScoped(implementType);
}
}
}
return services;
}
Program类注入这个方法
builder.Services.AddRepository();
使用仓储
创建一个菜单仓储接口继承自IBaseRepository
using DataModel.Table;
using IRepository.DI;
namespace IRepository
{
/// <summary>
/// 菜单仓储接口
/// </summary>
public interface IMenuRepository : IBaseRepository<MenuInfo>
{
/// <summary>
/// 扩展方法(私有方法)
/// </summary>
/// <returns></returns>
string Test();
}
}
创建一个菜单仓储实现类,继承泛型仓储和菜单仓储接口
可以通过以下两个构造函数实现SQL日志的打印,这边选择需要日志
using DataModel.Table;
using IRepository;
using Microsoft.Extensions.Logging;
using SqlSugar;
namespace Repository
{
/// <summary>
/// 菜单仓储类
/// </summary>
public class MenuRepository : BaseRepository<MenuInfo>, IMenuRepository
{
/// <summary>
/// 无日志构造函数(不需要日志就放开注释)
/// </summary>
/// <param name="context"></param>
// public MenuRepository(ISqlSugarClient context) : base(context)
// {
// base.Context = context;
// }
/// <summary>
/// 有日志构造函数(需要日志就放开注释)
/// </summary>
/// <param name="context"></param>
/// <param name="logger"></param>
public MenuRepository(ISqlSugarClient context, ILogger<MenuRepository> logger) : base(context, logger)
{
base.Context = context;
}
/// <summary>
/// 扩展方法(私有方法)
/// </summary>
/// <returns></returns>
public string Test()
{
return "Test";
}
}
}
在业务实现类中使用构造函数注入
/// <summary>
/// 业务实现类
/// </summary>
public class HomeDataService: IHomeDataService
{
private readonly IMenuRepository _menuRepository;
public HomeDataService(IMenuRepository menuRepository)
{
_menuRepository = menuRepository;
}
public string Get()
{
// 可通过仓储调用SqlSugarClient
List<MenuInfo> asSugarClient = _menuRepository.AsSugarClient().Queryable<MenuInfo>().ToList();
// 调用仓储内扩展方法
string test = _menuRepository.Test();
// 调用父仓储公共扩展方法
var list = _menuRepository.ToPageList(1,2);
// 返回 "Test"
return test;
}
}
/// <summary>
/// 业务接口
/// </summary>
public interface IHomeDataService: ISingleton
{
string Get();
}
根据业务完成解耦