1 CoreCms.Net.Model.ViewModels.Basics.IPageList<T>
namespace CoreCms.Net.Model.ViewModels.Basics
{
///<typeparam name="T">泛型类型实例(1个指定实体的类型实例)。</typeparam>
/// <summary>
/// 【逻辑分页列表--接口】
/// <remarks>
/// 摘要:
/// 通过继承该接口的具体实现类中的属性成员实例,逻辑的从数据源中加载指定1页中的数据,存储到1逻辑页中,从而尽量少的从指定表加载数据,从而尽量降低内存的消耗。
/// 说明:
/// 逻辑分页交互操作对象是当前程序与数据库的指定表。
/// </remarks>
/// </summary>
public interface IPageList<T> : IList<T>
{
#region 属性
/// <summary>
/// 【当前页】
/// <remarks>
/// 摘要:
/// 获取/设置当前页,当前逻辑(内存)页面的整型索引值,从“0”开始计算。
/// </remarks>
/// </summary>
int PageIndex { get; }
/// <summary>
/// 【页面大小】
/// <remarks>
/// 摘要:
/// 获取/设置页面大小,即1逻辑(内存)页面最多所存储的实例项的整型个数值。
/// </remarks>
/// </summary>
int PageSize { get; }
/// <summary>
/// 【总计值】
/// <remarks>
/// 摘要:
/// 获取/设置数据源实例项的整型总计值。
/// </remarks>
/// </summary>
int TotalCount { get; }
/// <summary>
/// 【总页数】
/// <remarks>
/// 摘要:
/// 获取/设置总页数,即数据源实例项,可以分为逻辑页数的总计值。
/// </remarks>
/// </summary>
int TotalPages { get; }
/// <summary>
/// 【上1页?】
/// <remarks>
/// 摘要:
/// 获取1个值false(没有)/true(有),该值指示在逻辑(内存)分页操作中当前页是否有上1页(第1页之前没有上1页)。
/// </remarks>
/// </summary>
bool HasPreviousPage { get; }
/// <summary>
/// 【下1页?】
/// <remarks>
/// 摘要:
/// 获取1个值false(没有)/true(有),该值指示在逻辑(内存)分页操作中当前页是否有下1页(最后1页之后没有下1页)。
/// </remarks>
/// </summary>
bool HasNextPage { get; }
#endregion
}
}
2 CoreCms.Net.Model.ViewModels.Basics.PageList<T>
namespace CoreCms.Net.Model.ViewModels.Basics
{
///<typeparam name="T">泛型类型实例(1个指定实体的类型实例)。</typeparam>
/// <summary>
/// 【逻辑分页列表--类】
/// <remarks>
/// 摘要:
/// 通过该类及其属性成员实例,只逻辑的从数据源中加载指定1页中的数据,存储到1(逻辑)页中,从而尽量少的从指定表加载数据,从而尽量降低内存的消耗。
/// 说明:
/// (逻辑)分页交互操作对象是当前程序与数据库的指定表。
/// [Serializable]:
/// 序列化可以对象的状态信息转换成可以持久化或者可以传输形式的过程。一般是转为字节数据。而把字节数组还原成原来同等对象的过程成为反序列化。
/// 这里特指把逻辑分页实体中的所有数据换成可以进行网络传输的形式。
/// </remarks>
/// </summary>
[Serializable]
public class PageList<T> : List<T>, IPageList<T>
{
#region 拷贝构造方法
///<typeparam name="T">泛型类型实例(1个指定实体的类型实例)。</typeparam>
/// <param name="source">以“IQueryable”实例进行存储的1个指定类型的数据源(枚举数接口实例=长串型,包含:数组、列表、字典等)。</param>
/// <param name="pageIndex">分页操作中当前页的整型索引值。</param>
/// <param name="pageSize">1逻辑(内存)页面最多所存储的实例项的整型个数值。</param>
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过拷贝构造方法为该类中的属性成员赋值实例化初始值,并获取1逻辑(内存)页面内的所有数据。
/// </remarks>
/// </summary>
public PageList(IQueryable<T> source, int pageIndex, int pageSize)
{
var total = source.Count();
TotalCount = total;
TotalPages = total / pageSize;
if (total % pageSize > 0)
TotalPages++;
PageSize = pageSize;
PageIndex = pageIndex;
AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
}
/// <param name="source">以列表接口实例进行存储的1个指定类型的数据源(包含:数组、列表、字典等)。</param>
/// <param name="pageIndex">分页操作中当前页的整型索引值。</param>
/// <param name="pageSize">1逻辑(内存)页面最多所存储的实例项的整型个数值。</param>
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过拷贝构造方法为该类中的属性成员赋值实例化初始值,并获取1逻辑(内存)页面内的所有数据。
/// </remarks>
/// </summary>
public PageList(IList<T> source, int pageIndex, int pageSize)
{
TotalCount = source.Count();
TotalPages = TotalCount / pageSize;
if (TotalCount % pageSize > 0)
TotalPages++;
PageSize = pageSize;
PageIndex = pageIndex;
AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
}
/// <param name="source">以列表接口实例进行存储的1个指定类型的数据源(包含:数组、列表、字典等)。</param>
/// <param name="pageIndex">分页操作中当前页的整型索引值。</param>
/// <param name="pageSize">1逻辑(内存)页面最多所存储的实例项的整型个数值。</param>
/// <param name="totalCount">数据源实例项的整型总计值。</param>
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过拷贝构造方法为该类中的属性成员赋值实例化初始值,并获取1逻辑(内存)页面内的所有数据。
/// </remarks>
/// </summary>
public PageList(IEnumerable<T> source, int pageIndex, int pageSize, int totalCount)
{
TotalCount = totalCount;
TotalPages = TotalCount / pageSize;
if (TotalCount % pageSize > 0)
TotalPages++;
PageSize = pageSize;
PageIndex = pageIndex;
AddRange(source);
}
#endregion
#region 属性
/// <summary>
/// 【当前页】
/// <remarks>
/// 摘要:
/// 获取/设置当前页,当前逻辑(内存)页面的整型索引值,从“0”开始计算。
/// </remarks>
/// </summary>
public int PageIndex { get; }
/// <summary>
/// 【页面大小】
/// <remarks>
/// 摘要:
/// 获取/设置页面大小,即1逻辑(内存)页面最多所存储的实例项的整型个数值。
/// </remarks>
/// </summary>
public int PageSize { get; private set; }
/// <summary>
/// 【总计值】
/// <remarks>
/// 摘要:
/// 获取/设置数据源实例项的整型总计值。
/// </remarks>
/// </summary>
public int TotalCount { get; }
/// <summary>
/// 【总页数】
/// <remarks>
/// 摘要:
/// 获取/设置总页数,即数据源实例项,可以分为逻辑页数的总计值。
/// </remarks>
/// </summary>
public int TotalPages { get; }
/// <summary>
/// 【上1页?】
/// <remarks>
/// 摘要:
/// 获取1个值false(没有)/true(有),该值指示在逻辑(内存)分页操作中当前页是否有上1页(第1页之前没有上1页)。
/// </remarks>
/// </summary>
public bool HasPreviousPage => PageIndex > 0;
/// <summary>
/// 【下1页?】
/// <remarks>
/// 摘要:
/// 获取1个值false(没有)/true(有),该值指示在逻辑(内存)分页操作中当前页是否有下1页(最后1页之后没有下1页)。
/// </remarks>
/// </summary>
public bool HasNextPage => PageIndex + 1 < TotalPages;
#endregion
}
}
3 CoreCms.Net.Core.AutoFac.AutofacModuleRegister
using Autofac;
using System.Reflection;
namespace CoreCms.Net.Core.AutoFac
{
/// <summary>
/// 【Autofac模型注入--类】
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员把指定的程序集(*.dll)依赖注入到Autofac容器中。
/// </remarks>
/// </summary>
public class AutofacModuleRegister : Autofac.Module
{
/// <param name="builder">Autofac依赖注入容器实例。</param>
/// <summary>
/// 【载入】
/// <remarks>
/// 摘要:
/// 通过该方法把指定程序集中的所有实例依赖注入到Autofac容器中。
/// </remarks>
/// </summary>
protected override void Load(ContainerBuilder builder)
{
//获取当前程序启动项程序集(*.dll)文件所在目录(文件夹)的绝对路径字符串(这里特指“..\bin\Debug\net7.0”)。
var basePath = AppContext.BaseDirectory;
#region 带有接口层的服务注入
//var servicesDllFile = Path.Combine(basePath, "CoreCms.Net.Services.dll");
var repositoryDllFile = Path.Combine(basePath, "CoreCms.Net.Repository.dll");
/* if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
var msg = "Repository.dll和Services.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。";
throw new Exception(msg);
}*/
// 获取 Service.dll 程序集服务,并注册
/*var assemblysServices = Assembly.LoadFrom(servicesDllFile);
//支持属性注入依赖重复
builder.RegisterAssemblyTypes(assemblysServices).AsImplementedInterfaces().InstancePerDependency()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
*/
// 获取 Repository.dll 程序集服务,并注册
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
//支持属性注入依赖重复
builder.RegisterAssemblyTypes(assemblysRepository).AsImplementedInterfaces().InstancePerDependency()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies);
#endregion
}
}
}
4 Program.cs
#region AutoFac注册============================================================================
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
//获取所有控制器类型并使用属性注入
var controllerBaseType = typeof(ControllerBase);
containerBuilder.RegisterAssemblyTypes(typeof(Program).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired();
containerBuilder.RegisterModule(new AutofacModuleRegister());
});
#endregion
5 CoreCms.Net.IRepository.UnitOfWork.IUnitOfWork
using SqlSugar;
namespace CoreCms.Net.IRepository.UnitOfWork
{
/// <summary>
/// 【工作单元--类】
/// <remarks>
/// 摘要:
/// 通过继承该接口的具体实现类中的方法成员,获取SqlSugarScope(用单例AddSingleton 单例)上下文中间件实例,从而为实现实体与表的CURD操作提供支撑。
/// </remarks>
/// </summary>
public interface IUnitOfWork
{
#region 方法
/// <summary>
/// 【获取数据库数据端】
/// <remarks>
/// 摘要:
/// 获取SqlSugarScope(用单例AddSingleton 单例)上下文中间件实例,该实例为通过 SqlSugar中间件实现实体与表的CURD操作提供支撑。
/// </remarks>
/// </summary>
SqlSugarScope GetDbClient();
/// <summary>
/// 【事务开始】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,该方法主要指开启1个事务。
/// </remarks>
/// </summary>
void BeginTran();
/// <summary>
/// 【事务提交】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,该方法主要指把1个事务中的所有操作进行提交到指定的数据库中。
/// </remarks>
/// </summary>
void CommitTran();
/// <summary>
/// 【事务回滚】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,当把1个事务中的所有操作进行提交到指定的数据库的过程中如果出现异常时,则通过该方法实现回滚。
/// </remarks>
/// </summary>
void RollbackTran();
#endregion
}
}
6 CoreCms.Net.IRepository.UnitOfWork.UnitOfWork
using CoreCms.Net.IRepository.UnitOfWork;
//using CoreCms.Net.Loging;
//using NLog;
using SqlSugar;
using SqlSugar.IOC;
namespace CoreCms.Net.Repository.UnitOfWork
{
/// <summary>
/// 【工作单元--类】
/// <remarks>
/// 摘要:
/// 通过该类中的成员获取SqlSugarScope(用单例AddSingleton 单例)上下文中间件实例,从而为实现实体与表的CURD操作提供支撑。
/// </remarks>
/// </summary>
public class UnitOfWork : IUnitOfWork
{
#region 拷贝构造方法与变量
/// <summary>
/// 【上下文中间件实例】
/// <remarks>
/// 摘要:
/// ISqlSugarClient(用 AddScoped 每次请求一个实例)上下文中间件实例,该实例为通过 SqlSugar中间件实现实体与表的CURD操作提供支撑。
/// </remarks>
/// </summary>
private readonly ISqlSugarClient _sqlSugarClient;
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过该拷贝构造方法,对当前类中变量成员进行实例化。
/// </remarks>
/// </summary>
public UnitOfWork()
{
_sqlSugarClient = DbScoped.SugarScope;
}
#endregion
#region 方法
/// <summary>
/// 【获取数据库数据端】
/// <remarks>
/// 摘要:
/// 获取SqlSugarScope(用单例AddSingleton 单例)上下文中间件实例,该实例为通过 SqlSugar中间件实现实体与表的CURD操作提供支撑。
/// </remarks>
/// </summary>
public SqlSugarScope GetDbClient()
{
// 必须要as,后边会用到切换数据库操作
return _sqlSugarClient as SqlSugarScope;
}
/// <summary>
/// 【事务开始】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,该方法主要指开启1个事务。
/// </remarks>
/// </summary>
public void BeginTran()
{
GetDbClient().BeginTran();
}
/// <summary>
/// 【事务提交】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,该方法主要指把1个事务中的所有操作进行提交到指定的数据库中。
/// </remarks>
/// </summary>
public void CommitTran()
{
try
{
GetDbClient().CommitTran();
}
catch (Exception ex)
{
GetDbClient().RollbackTran();
// NLogUtil.WriteFileLog(LogLevel.Error, LogType.Web, "事务提交异常", "事务提交异常", new Exception("事务提交异常", ex));
throw;
}
}
/// <summary>
/// 【事务回滚】
/// <remarks>
/// 摘要:
/// 该方法通过事务操作实现实现实体与表的CURD操作提供支撑,当把1个事务中的所有操作进行提交到指定的数据库的过程中如果出现异常时,则通过该方法实现回滚。
/// </remarks>
/// </summary>
public void RollbackTran()
{
GetDbClient().RollbackTran();
}
#endregion
}
}
12 CoreCms.Net.Web.Admin.Controllers.SysRoleController
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel;
using CoreCms.Net.IRepository;
namespace CoreCms.Net.Web.Admin.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class SysRoleController : ControllerBase
{
private readonly ISysRoleRepository _dal;
public SysRoleController(ISysRoleRepository dal)
{
_dal = dal;
}
#region 获取列表============================================================
[HttpPost]
[Description("获取列表")]
public async Task</*AdminUiCallBack*/ bool> GetPageList()
{
var v = await _dal.QueryPageAsync(null,"");
return true;
}
#endregion
}
}
对以上功能更为具体实现和注释见:230727_002CoreShop230628(逻辑分页、AutoFac注入、工作单元与仓储)。