基础层
1、Cloud.Core项目是核心项目,主要实现缓存的操作、dapper操作、EFRepository、PageList、日志等操作
2、Cloud.Utility属于帮助类
领域层
3、Cloud.Entity实体对象,存放数据库映射实体、FluentAPI配置、枚举字典、DbContext等
4、Cloud.UnitOfWork,操作数据库的网关,里面封装了对仓储的操作、dapper的操作、事务等
服务层
5、Cloud.Service业务逻辑的实现
6、Cloud.Dto数据传输对象,实体对象不直接和表现层接触,通过dto互转
表现层
7、Cloud.Framework,表现层框架,封装了超类controller,全局授权过滤器,全局异常过滤器,ActionFilter,HtmlHelper等操作
8、Cloud.Boss启动项目
使用的技术
基于.NETCore2.0的ASP.NETCoreMVC
基于.NETCore2.0的EF
Dapper
Mysql
前端框架:aceAdmin(http://ace.jeka.by/#)
技术要点
1、实体基类定义
2、泛型仓储的封装
2.1、仓储接口的定义,泛型约束T必须是BaseEntity类型
publicinterfaceIRepository
{
DatabaseFacadeDatabase{get;}
IQueryable
intSaveChanges();
Task
voidDisposed();
boolDelete(List
boolDelete(Tentity,boolisSaveChange=true);
Task
Task
Task
Task>GetListAsync(Expression
TGet(objectid);
TGet(Expression
Task
Task
boolInsert(List
boolInsert(Tentity,boolisSaveChange=true);
Task
Task
boolUpdate(List
boolUpdate(Tentity,boolisSaveChange=true,List
Task
Task
}
publicinterfaceIRepository
{
DatabaseFacadeDatabase{get;}
IQueryable
intSaveChanges();
Task
voidDisposed();
boolDelete(List
boolDelete(Tentity,boolisSaveChange=true);
Task
Task
Task
Task>GetListAsync(Expression
TGet(objectid);
TGet(Expression
Task
Task
boolInsert(List
boolInsert(Tentity,boolisSaveChange=true);
Task
Task
boolUpdate(List
boolUpdate(Tentity,boolisSaveChange=true,List
Task
Task
}
2.2、仓储接口的实现
publicclassRepository
{
DbContext_dbContext;
publicRepository(DbContextdbContext)
{
_dbContext=dbContext;
}
publicintSaveChanges()
{
return_dbContext.SaveChanges();
}
publicasyncTask
{
returnawait_dbContext.SaveChangesAsync();
}
publicvoidDisposed()
{
thrownewException("不允许在这里释放上下文,请在UnitOfWork中操作");
_dbContext.Dispose();
}
#region插入数据
publicboolInsert(Tentity,boolisSaveChange=true)
{
_dbContext.Set
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
_dbContext.Set
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
publicboolInsert(List
{
_dbContext.Set
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
_dbContext.Set
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
#endregion
#region更新数据
publicboolUpdate(Tentity,boolisSaveChange=true,List
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicboolUpdate(List
{
if(entitys==null||entitys.Count==0)
{
returnfalse;
}
entitys.ForEach(c=>{
Update(c,false);
});
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
publicasyncTask
{
if(entitys==null||entitys.Count==0)
{
returnfalse;
}
entitys.ForEach(c=>{
_dbContext.Set
_dbContext.Entry
});
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
#endregion
#region删除
publicboolDelete(Tentity,boolisSaveChange=true)
{
_dbContext.Set
_dbContext.Set
returnisSaveChange?SaveChanges()>0:false;
}
publicboolDelete(List
{
entitys.ForEach(entity=>
{
_dbContext.Set
_dbContext.Set
});
returnisSaveChange?SaveChanges()>0:false;
}
publicvirtualasyncTask
{
_dbContext.Set
_dbContext.Set
returnisSaveChange?awaitSaveChangesAsync()>0:false;
}
publicvirtualasyncTask
{
entitys.ForEach(entity=>
{
_dbContext.Set
_dbContext.Set
});
returnisSaveChange?awaitSaveChangesAsync()>0:false;
}
#endregion
publicIQueryable
//publicasyncTask
publicDatabaseFacadeDatabase=>_dbContext.Database;
#region查找
publicTGet(objectid)
{
return_dbContext.Set
}
publicTGet(Expression
{
return_dbContext.Set
}
publicasyncTask
{
returnawait_dbContext.Set
}
publicasyncTask
{
returnawait_dbContext.Set
}
publicasyncTask>GetListAsync(Expression
{
returnawait_dbContext.Set
}
publicasyncTask
{
if(predicate==null)
{
predicate=c=>true;
}
returnawaitTask.Run(()=>_dbContext.Set
}
publicvoidDispose()
{
thrownewNotImplementedException();
}
#endregion
}
publicclassRepository
{
DbContext_dbContext;
publicRepository(DbContextdbContext)
{
_dbContext=dbContext;
}
publicintSaveChanges()
{
return_dbContext.SaveChanges();
}
publicasyncTask
{
returnawait_dbContext.SaveChangesAsync();
}
publicvoidDisposed()
{
thrownewException("不允许在这里释放上下文,请在UnitOfWork中操作");
_dbContext.Dispose();
}
#region插入数据
publicboolInsert(Tentity,boolisSaveChange=true)
{
_dbContext.Set
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
_dbContext.Set
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
publicboolInsert(List
{
_dbContext.Set
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
_dbContext.Set
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
#endregion
#region更新数据
publicboolUpdate(Tentity,boolisSaveChange=true,List
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicboolUpdate(List
{
if(entitys==null||entitys.Count==0)
{
returnfalse;
}
entitys.ForEach(c=>{
Update(c,false);
});
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicasyncTask
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
publicasyncTask
{
if(entitys==null||entitys.Count==0)
{
returnfalse;
}
entitys.ForEach(c=>{
_dbContext.Set
_dbContext.Entry
});
if(isSaveChange)
{
returnawaitSaveChangesAsync()>0;
}
returnfalse;
}
#endregion
#region删除
publicboolDelete(Tentity,boolisSaveChange=true)
{
_dbContext.Set
_dbContext.Set
returnisSaveChange?SaveChanges()>0:false;
}
publicboolDelete(List
{
entitys.ForEach(entity=>
{
_dbContext.Set
_dbContext.Set
});
returnisSaveChange?SaveChanges()>0:false;
}
publicvirtualasyncTask
{
_dbContext.Set
_dbContext.Set
returnisSaveChange?awaitSaveChangesAsync()>0:false;
}
publicvirtualasyncTask
{
entitys.ForEach(entity=>
{
_dbContext.Set
_dbContext.Set
});
returnisSaveChange?awaitSaveChangesAsync()>0:false;
}
#endregion
publicIQueryable
//publicasyncTask
publicDatabaseFacadeDatabase=>_dbContext.Database;
#region查找
publicTGet(objectid)
{
return_dbContext.Set
}
publicTGet(Expression
{
return_dbContext.Set
}
publicasyncTask
{
returnawait_dbContext.Set
}
publicasyncTask
{
returnawait_dbContext.Set
}
publicasyncTask>GetListAsync(Expression
{
returnawait_dbContext.Set
}
publicasyncTask
{
if(predicate==null)
{
predicate=c=>true;
}
returnawaitTask.Run(()=>_dbContext.Set
}
publicvoidDispose()
{
thrownewNotImplementedException();
}
#endregion
}
3、表部分字段更新实现
EF默认的更新方式是一个实体对应的表全部字段更新,那么我们想更新表的部分字段怎么处理?
首先定义需要更新的字段:
publicclassPropertyExpression
{
privatePropertyExpression(){}
privatestaticList
publicstaticPropertyExpression
{
get
{
propertyList.Clear();
returnnewPropertyExpression
}
}
publicPropertyExpression
{
varrtn="";
if(expr.BodyisUnaryExpression)
{
rtn=((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
}
elseif(expr.BodyisMemberExpression)
{
rtn=((MemberExpression)expr.Body).Member.Name;
}
elseif(expr.BodyisParameterExpression)
{
rtn=((ParameterExpression)expr.Body).Type.Name;
}
propertyList.Add(rtn);
returnthis;
}
publicList
{
returnpropertyList;
}
}
publicclassPropertyExpression
{
privatePropertyExpression(){}
privatestaticList
publicstaticPropertyExpression
{
get
{
propertyList.Clear();
returnnewPropertyExpression
}
}
publicPropertyExpression
{
varrtn="";
if(expr.BodyisUnaryExpression)
{
rtn=((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
}
elseif(expr.BodyisMemberExpression)
{
rtn=((MemberExpression)expr.Body).Member.Name;
}
elseif(expr.BodyisParameterExpression)
{
rtn=((ParameterExpression)expr.Body).Type.Name;
}
propertyList.Add(rtn);
returnthis;
}
publicList
{
returnpropertyList;
}
}
EF更新的处理
publicboolUpdate(Tentity,boolisSaveChange=true,List
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
publicboolUpdate(Tentity,boolisSaveChange=true,List
{
if(entity==null)
{
returnfalse;
}
_dbContext.Set
if(updatePropertyList==null)
{
_dbContext.Entry
}
else
{
updatePropertyList.ForEach(c=>{
_dbContext.Entry(entity).Property(c).IsModified=true;//部分字段更新的写法
});
}
if(isSaveChange)
{
returnSaveChanges()>0;
}
returnfalse;
}
使用
varentity=_unitOfWork.SysRoleRep.Get(model.RoleId);
if(entity==null)
{
thrownewException("要查找的对象不存在");
}
entity.Name=model.RoleName;
varupdatedPropertyList=PropertyExpression
_unitOfWork.SysRoleRep.Update(entity,true,updatedPropertyList);
varentity=_unitOfWork.SysRoleRep.Get(model.RoleId);
if(entity==null)
{
thrownewException("要查找的对象不存在");
}
entity.Name=model.RoleName;
varupdatedPropertyList=PropertyExpression
_unitOfWork.SysRoleRep.Update(entity,true,updatedPropertyList);
4、动态加载实体到DbContext
publicclassEntityTypeConfiguration
{
publicvoidConfigure(EntityTypeBuilder
{
RelyConfigure(builder);
}
publicvirtualvoidRelyConfigure(EntityTypeBuilder
{
}
}
publicclassEntityTypeConfiguration
{
publicvoidConfigure(EntityTypeBuilder
{
RelyConfigure(builder);
}
publicvirtualvoidRelyConfigure(EntityTypeBuilder
{
}
}
publicclassSys_Error_LogConfiguration:EntityTypeConfiguration
{
publicoverridevoidRelyConfigure(EntityTypeBuilder
{
builder.ToTable("sys_error_log");
builder.HasKey(x=>x.Id);
base.RelyConfigure(builder);
}
}
publicclassSys_Error_LogConfiguration:EntityTypeConfiguration
{
publicoverridevoidRelyConfigure(EntityTypeBuilder
{
builder.ToTable("sys_error_log");
builder.HasKey(x=>x.Id);
base.RelyConfigure(builder);
}
}
publicclassEfDbContext:DbContext
{
publicEfDbContext(DbContextOptions
{
}
//配置数据库连接
protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptionsBuilder)
{
//optionsBuilder.UseSqlServer("xxxxconnectionstring");
base.OnConfiguring(optionsBuilder);
}
//第一次使用EF功能时执行一次,以后不再执行
protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder)
{
//获取当前程序集中有基类并且基类是泛型的类
vartypesToRegister=Assembly.GetExecutingAssembly().GetTypes().Where(c=>c.BaseType!=null&&c.BaseType.IsGenericType).ToList();
foreach(vartypeintypesToRegister)
{
//泛型定义相同
if(type.BaseType.GetGenericTypeDefinition()==typeof(EntityTypeConfiguration))
{
dynamicconfigurationInstance=Activator.CreateInstance(type);
modelBuilder.ApplyConfiguration(configurationInstance);
}
}
base.OnModelCreating(modelBuilder);
}
}
publicclassEfDbContext:DbContext
{
publicEfDbContext(DbContextOptions
{
}
//配置数据库连接
protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptionsBuilder)
{
//optionsBuilder.UseSqlServer("xxxxconnectionstring");
base.OnConfiguring(optionsBuilder);
}
//第一次使用EF功能时执行一次,以后不再执行
protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder)
{
//获取当前程序集中有基类并且基类是泛型的类
vartypesToRegister=Assembly.GetExecutingAssembly().GetTypes().Where(c=>c.BaseType!=null&&c.BaseType.IsGenericType).ToList();
foreach(vartypeintypesToRegister)
{
//泛型定义相同
if(type.BaseType.GetGenericTypeDefinition()==typeof(EntityTypeConfiguration))
{
dynamicconfigurationInstance=Activator.CreateInstance(type);
modelBuilder.ApplyConfiguration(configurationInstance);
}
}
base.OnModelCreating(modelBuilder);
}
}
5、工作单元
工作单元是对仓储和事务的封装
原理参考:https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
publicclassEfUnitOfWork:IUnitOfWork
{
privateEfDbContext_dbContext;//每次请求上下文只会创建一个
publicEfUnitOfWork(EfDbContextcontext)
{
this._dbContext=context;
}
publicintSaveChanges()
{
return_dbContext.SaveChanges();
}
publicasyncTask
{
returnawait_dbContext.SaveChangesAsync();
}
privatebooldisposed=false;
protectedvirtualvoidDispose(booldisposing)
{
if(!this.disposed)
{
if(disposing)
{
_dbContext.Dispose();//随着工作单元的销毁而销毁
}
}
this.disposed=true;
}
publicvoidDispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
publicIDbContextTransactionBeginTransaction()
{
varscope=_dbContext.Database.BeginTransaction();
returnscope;
}
publicList
{
varcon=_dbContext.Database.GetDbConnection();
if(con.State!=ConnectionState.Open)
{
con.Open();
}
varlist=MysqlDapperReader.SqlQuery
returnlist;
//thrownewNotImplementedException();
}
publicTask>SqlQueryAsync
{
thrownewNotImplementedException();
}
#regionSysRepository
privateIRepository
publicIRepository
{
get
{
if(_sysUserRep==null)
{
//vars=HttpContext.Current.Items["currentUser"];
//vars=HttpContext.Current.RequestServices.GetService
//HttpContext.RequestServices.GetService
_sysUserRep=newRepository
}
return_sysUserRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysRoleRep==null)
{
_sysRoleRep=newRepository
}
return_sysRoleRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysRoleUserRep==null)
{
_sysRoleUserRep=newRepository
}
return_sysRoleUserRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysPermissionRep==null)
{
_sysPermissionRep=newRepository
}
return_sysPermissionRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysModuleRep==null)
{
_sysModuleRep=newRepository
}
return_sysModuleRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysErrorLogRep==null)
{
_sysErrorLogRep=newRepository
}
return_sysErrorLogRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysOperationLogRep==null)
{
_sysOperationLogRep=newRepository
}
return_sysOperationLogRep;
}
}
#endregion
}
publicclassEfUnitOfWork:IUnitOfWork
{
privateEfDbContext_dbContext;//每次请求上下文只会创建一个
publicEfUnitOfWork(EfDbContextcontext)
{
this._dbContext=context;
}
publicintSaveChanges()
{
return_dbContext.SaveChanges();
}
publicasyncTask
{
returnawait_dbContext.SaveChangesAsync();
}
privatebooldisposed=false;
protectedvirtualvoidDispose(booldisposing)
{
if(!this.disposed)
{
if(disposing)
{
_dbContext.Dispose();//随着工作单元的销毁而销毁
}
}
this.disposed=true;
}
publicvoidDispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
publicIDbContextTransactionBeginTransaction()
{
varscope=_dbContext.Database.BeginTransaction();
returnscope;
}
publicList
{
varcon=_dbContext.Database.GetDbConnection();
if(con.State!=ConnectionState.Open)
{
con.Open();
}
varlist=MysqlDapperReader.SqlQuery
returnlist;
//thrownewNotImplementedException();
}
publicTask>SqlQueryAsync
{
thrownewNotImplementedException();
}
#regionSysRepository
privateIRepository
publicIRepository
{
get
{
if(_sysUserRep==null)
{
//vars=HttpContext.Current.Items["currentUser"];
//vars=HttpContext.Current.RequestServices.GetService
//HttpContext.RequestServices.GetService
_sysUserRep=newRepository
}
return_sysUserRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysRoleRep==null)
{
_sysRoleRep=newRepository
}
return_sysRoleRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysRoleUserRep==null)
{
_sysRoleUserRep=newRepository
}
return_sysRoleUserRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysPermissionRep==null)
{
_sysPermissionRep=newRepository
}
return_sysPermissionRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysModuleRep==null)
{
_sysModuleRep=newRepository
}
return_sysModuleRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysErrorLogRep==null)
{
_sysErrorLogRep=newRepository
}
return_sysErrorLogRep;
}
}
privateIRepository
publicIRepository
{
get
{
if(_sysOperationLogRep==null)
{
_sysOperationLogRep=newRepository
}
return_sysOperationLogRep;
}
}
#endregion
}
6、业务的实现方式
以前我是service中直接创建仓储然后用仓储操作数据库,方式如下:
这种方式比较繁琐,后来我将创建仓储统一放在工作单元中进行,在service中直接创建UnitOfWork,方式如下:
7、Service的动态注册
publicstaticclassAutoIocRegister
{
///
///动态注入IOC,注意类和接口的命名规则,接口在类名前面加"I"
///
///
///
publicstaticvoidBatchAddScoped(thisIServiceCollectionservices,stringassemblyName)
{
varlibs=DependencyContext.Default.CompileLibraries;
varserviceLib=libs.Where(c=>c.Name.Contains(assemblyName)).FirstOrDefault();
varassembly=AssemblyLoadContext.Default.LoadFromAssemblyName(newAssemblyName(serviceLib.Name));
varserviceClassList=assembly.GetTypes().Where(c=>c.IsClass).ToList();
foreach(variteminserviceClassList)
{
varinterfaceName="I"+item.Name;
varinterfaceType=assembly.GetTypes().Where(c=>c.IsInterface&&c.Name==interfaceName).FirstOrDefault();
if(interfaceType==null)continue;
services.AddScoped(interfaceType,item);
}
}
}
publicstaticclassAutoIocRegister
{
///
///动态注入IOC,注意类和接口的命名规则,接口在类名前面加"I"
///
///
///
publicstaticvoidBatchAddScoped(thisIServiceCollectionservices,stringassemblyName)
{
varlibs=DependencyContext.Default.CompileLibraries;
varserviceLib=libs.Where(c=>c.Name.Contains(assemblyName)).FirstOrDefault();
varassembly=AssemblyLoadContext.Default.LoadFromAssemblyName(newAssemblyName(serviceLib.Name));
varserviceClassList=assembly.GetTypes().Where(c=>c.IsClass).ToList();
foreach(variteminserviceClassList)
{
varinterfaceName="I"+item.Name;
varinterfaceType=assembly.GetTypes().Where(c=>c.IsInterface&&c.Name==interfaceName).FirstOrDefault();
if(interfaceType==null)continue;
services.AddScoped(interfaceType,item);
}
}
}
调用:
services.BatchAddScoped("Cloud.Service");
services.BatchAddScoped("Cloud.Service");
8、日志记录
日志分操作日志和错误日志,可以设置在数据库和文本中同时记录:
通过全局过滤器GlobalExceptionFilter和GlobalAuthorizeFilter处理
9、前端的封装(分页、弹出层、ajax等)
先放几张图吧,详细的以后再介绍
演示地址:http://cloud.eggtwo.com/main/index
●编号172,输入编号直达本文
更多推荐《25个技术类公众微信》