我是用的是vs2022
IRepositry、Repository仓储层,负责处理数据 就是ADO。net那套东西。
IService、Service 业务服务层,三层架构的BLL。
Model 存放实体类
首先创建者几个目录
app里面创建webapi项目
其他目录创建类项目
然后一步一步来,创建model层
这个是实体,看不懂的去sqlsugar官网
然后我们开始处理仓储层,创建IBaseRepository类(j接口类),里面添加接口
泛型类约束:
添加内容:
/// <summary>
/// 根据条件查询数据
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
OrderByType orderByType, bool blUseNoLock = false);
然后我们添加BaseRepository类来实现接口
实现接口:
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, bool blUseNoLock = false)
{
return blUseNoLock
? await DbBaseClient.Queryable<T>().With(SqlWith.NoLock).FirstAsync(predicate)
: await DbBaseClient.Queryable<T>().FirstAsync(predicate);
}
到这里仓储层就完结了,接下来我们处理服务层的东西,上面我们说过,可以吧仓储理解为三层,仓储层的DLL层已经弄完了,我们开始弄bll层,bll要调用dll层。
我们创建IBaseServices接口类:
这里的约束里面是只有class,没有new(),说明继承这个接口类的时候不用构造函数
然后在里面添加接口:
/// <summary>
/// 根据条件查询数据
/// </summary>
/// <param name="predicate">条件表达式树</param>
/// <param name="orderByPredicate">排序字段</param>
/// <param name="orderByType">排序顺序</param>
/// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
/// <returns></returns>
Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByPredicate,
OrderByType orderByType, bool blUseNoLock = false);
然后我们添加BaseServices类来实现IBaseServices的接口
public IBaseRepository BaseDal;要明白这个就是用来调用仓储层的接口的,server层调用Repository的方法,Repository的方法来访问数据库,可以这么理解
接口实现:
public async Task<T> QueryByClauseAsync(Expression<Func<T, bool>> predicate,
Expression<Func<T, object>> orderByPredicate, OrderByType orderByType, bool blUseNoLock = false)
{
return await BaseDal.QueryByClauseAsync(predicate, orderByPredicate, orderByType, blUseNoLock);
}
仓储模式基本算搞定了。
开始做数据展示了
我们还是先创建仓储层的接口IOPS_Monitor_Item_ResultRepository类,然后继承IBaseServices,这样我们的IOPS_Monitor_Item_ResultRepository接口类就有了IBaseServices接口类的所有接口的东西
using Model.Entites.System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRepository
{
//上面的截图中有 IBaseRepository<T> where T : class, new()约束,意思是:T可以传任何实体类进来,class限定只能类来继承,new()指定继承累必须有构造函数,而我这里没有,是省略了或者说C#是默认给你隐藏了,因为你不需要在构造函数里面干啥事
public interface IOPS_Monitor_Item_ResultRepository : IBaseRepository<OPS_Monitor_Item_Result>
{
}
}
我们上面写了IOPS_Monitor_Item_ResultRepository接口,就要实现接口:
using IRepository;
using Model.Entites.System;
using Repository.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Repository
{
//这里我们已经继承了BaseRepository接口,实际上如果我们把所有的接口都在BaseRepository里面实现了,就不需要在继承IOPS_Monitor_Item_ResultRepository这个接口了
//,之所以还要继承是为了有面这个实体有需要实现的特殊逻辑,可以单独写在这里面方便扩展
public class OPS_Monitor_Item_ResultRepository:BaseRepository<OPS_Monitor_Item_Result>, IOPS_Monitor_Item_ResultRepository
{
public OPS_Monitor_Item_ResultRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
}
}
仓储层完成了(对应的三层DLL)
那我们开始弄服务层(bll)
老样子创建服务层IOPS_Monitor_Item_ResultServices接口:
using Model.Entites.System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IServices
{
public interface IOPS_Monitor_Item_ResultServices:IBaseServices<OPS_Monitor_Item_Result>
{
}
}
实现服务层OPS_Monitor_Item_ResultServices接口:
using IRepository;
using IServices;
using Model.Entites.System;
using Repository.UnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Services
{
public class OPS_Monitor_Item_ResultServices:BaseServices<OPS_Monitor_Item_Result>, IOPS_Monitor_Item_ResultServices
{
//定义的事务调用
private readonly IUnitOfWork _unitOfWork;
private readonly IOPS_Monitor_Item_ResultRepository _db;
public OPS_Monitor_Item_ResultServices(IUnitOfWork unitOfWork, IOPS_Monitor_Item_ResultRepository db )
{
_db=db;
// BaseDal 这个地方是不是很熟悉,他就是BaseServices类中的 public IBaseRepository<T> BaseDal
//这个东西,这个就是给你调用仓储层的方法用的
BaseDal = db;
_unitOfWork =unitOfWork;
}
}
}
这个仓储的第一个模型搞完,开始调用,创建要给控制器:
using IServices;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Model.Entites.System;
namespace WEBAPI6._0.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class MonitorController : ControllerBase
{
//用哪个接口,你就在构造函数里面去初始化赋值
private readonly IOPS_Monitor_Item_ResultServices _OPS_Monitor_Item_Result;
public MonitorController(IOPS_Monitor_Item_ResultServices OPS_Monitor_Item_Result )
{
_OPS_Monitor_Item_Result = OPS_Monitor_Item_Result;
}
[HttpPost]
public async Task<List<OPS_Monitor_Item_Result>> ceshi()
{
string id = "168672";
string datetimestring = "2022-05-01";
List<OPS_Monitor_Item_Result> result= await _OPS_Monitor_Item_Result.QueryListByClauseAsync(p=>p.operation_id== id&&p.monitoring_time>=Convert.ToDateTime(datetimestring),p=>p.monitoring_time,SqlSugar.OrderByType.Desc);
return result;
}
}
}
这里还有 数据库链接服务,autofac的ioc没写
我只直接贴代码不想写了:
SqlSugarSetup类
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Net.Configuration
{
public static class SqlSugarSetup
{
public static void AddSqlSugarSetup(this IServiceCollection services) {
if (services == null) throw new ArgumentNullException(nameof(services));
//注入 ORM
SugarIocServices.AddSqlSugar(new IocConfig()
{
//数据库连接,这个地方我做了集成,你使用的时候可以直接链接字符串贴上来就能用
ConnectionString = AppSettingsConstVars.DbSqlConnection,
//判断数据库类型,这里可以写死 DbType ="SqlServer"
DbType = AppSettingsConstVars.DbDbType == IocDbType.MySql.ToString() ? IocDbType.MySql : IocDbType.SqlServer,
//是否开启自动关闭数据库连接-//不设成true要手动close
IsAutoCloseConnection = true,
});
//设置参数
services.ConfigurationSugar(db =>
{
db.CurrentConnectionConfig.InitKeyType = InitKeyType.Attribute;
//db.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices()
//{
// //判断是否开启redis设置二级缓存方式
// DataInfoCacheService = AppSettingsConstVars.RedisUseCache ? (ICacheService)new SqlSugarRedisCache() : new SqlSugarMemoryCache()
//};
//执行SQL 错误事件,可监控sql(暂时屏蔽,需要可开启)
//db.Aop.OnLogExecuting = (sql, p) =>
//{
// NLogUtil.WriteFileLog(NLog.LogLevel.Error, LogType.Other, "SqlSugar执行SQL错误事件打印Sql", sql);
//};
//执行SQL 错误事件
db.Aop.OnError = (exp) =>
{
// NLogUtil.WriteFileLog(NLog.LogLevel.Error, LogType.Other, "SqlSugar", "执行SQL错误事件", exp);
};
//设置更多连接参数
//db.CurrentConnectionConfig.XXXX=XXXX
//db.CurrentConnectionConfig.MoreSetting=new MoreSetting(){}
//读写分离等都在这儿设置
});
}
}
}
ioc:
AutofacModuleRegister
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autofac;
using System.Reflection;
namespace Net.Configuration.AutoFac
{
public class AutofacModuleRegister : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
var servicesDllFile1 = Path.Combine(basePath, "CoreCms.Net.Services.dll");
var repositoryDllFile1 = Path.Combine(basePath, "CoreCms.Net.Repository.dll");
var basePath1 = Directory.GetCurrentDirectory();
DirectoryInfo info = new DirectoryInfo(basePath1);
string repositoryDllFile = info.Parent.FullName+ "\\Repository\\bin\\Debug\\net6.0\\Repository.dll";
string servicesDllFile = info.Parent.FullName + "\\Services\\bin\\Debug\\net6.0\\Services.dll";
#region 带有接口层的服务注入
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
var msg = "Repository.dll和Services.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。";
throw new Exception(msg);
}
var basePath = AppContext.BaseDirectory;
var dllName1 = "Repository.dll";
#region 带有接口层的服务注入
var servicesDllFile = Path.Combine(basePath, "Services.Services.dll");
var repositoryDllFile = Path.Combine(basePath, "Repository.Repository.dll");
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
var msg = "Repository.dll和Services.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。";
throw new Exception(msg);
}
// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
//var cacheType = new List<Type>();
//if (AppSettingsConstVars.RedisConfigEnabled)
//{
// builder.RegisterType<RedisCacheAop>();
// cacheType.Add(typeof(RedisCacheAop));
//}
//else
//{
// builder.RegisterType<MemoryCacheAop>();
// cacheType.Add(typeof(MemoryCacheAop));
//}
// 获取 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);
// 获取 Service.dll 程序集服务,并注册
//var assemblysServices = Assembly.LoadFrom(servicesDllFile);
//builder.RegisterAssemblyTypes(assemblysServices)
// .AsImplementedInterfaces()
// .InstancePerDependency()
// .PropertiesAutowired()
// .EnableInterfaceInterceptors()//引用Autofac.Extras.DynamicProxy;
// .InterceptedBy(cacheType.ToArray());//允许将拦截器服务的列表分配给注册。
获取 Repository.dll 程序集服务,并注册
//var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
//builder.RegisterAssemblyTypes(assemblysRepository)
// .AsImplementedInterfaces()
// .PropertiesAutowired()
// .InstancePerDependency();
#endregion
}
}
}
随后在program中添加:
//添加本地路径获取支持
builder.Services.AddSingleton(new AppSettingsHelper());
//添加数据库连接SqlSugar注入支持
builder.Services.AddSqlSugarSetup( );
//配置跨域(CORS)
builder.Services.AddCorsSetup();
//自定义ioc使用autofac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule(new AutofacModuleRegister());
});
就可以跑起来了,记得生成数据库和数据,文中的unitOfWork和_unitOfWork可以删了,刚开始用不上的