创建仓储

首先需要建仓储接口层和仓储实现层

泛型仓储类如下(后续需要单独注入一次泛型仓储)

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

根据业务完成解耦


被这风吹散的人说Ta爱的不深,被这雨淋湿的人说Ta不会冷