注意:Aop一定要设置在你操作语句之前,不然不会生效,还有必须是同一个SqlSuagrClient才会有效
public SqlSugarClient GetInstance() { SqlSugarClient Db= new SqlSugarClient(new ConnectionConfig() { ConnectionString = "Server=.xxxxx", DbType = DbType.SqlServer, IsAutoCloseConnection = true, InitKeyType = InitKeyType.Attribute },db=>{ //如果是多库看标题6 //每次Sql执行前事件 db.Aop.OnLogExecuting = (sql, pars) => { //我可以在这里面写逻辑 //技巧:AOP中获取IOC对象 //var serviceBuilder = services.BuildServiceProvider(); //var log= serviceBuilder.GetService<ILogger<WeatherForecastController>>(); }; }); return db; } var db=GetInstance(); db.Queryable<T>().ToList();//执行操作会进事件
//SQL执行完 db.Aop.OnLogExecuted = (sql, pars) => { //执行完了可以输出SQL执行时间 (OnLogExecutedDelegate) Console.Write("time:" + db.Ado.SqlExecutionTime.ToString()); }; db.Aop.OnLogExecuting = (sql, pars) => //SQL执行前 { //获取原生SQL推荐 5.1.4.63 性能OK //UtilMethods.GetNativeSql(sql,pars) //获取无参数化SQL 影响性能只适合调试 //UtilMethods.GetSqlString(DbType.SqlServer,sql,pars) }; db.Aop.OnError = (exp) =>//SQL报错 { //获取原生SQL推荐 5.1.4.63 性能OK //UtilMethods.GetNativeSql(exp.sql,exp.parameters) //获取无参数SQL对性能有影响,特别大的SQL参数多的,调试使用 //UtilMethods.GetSqlString(DbType.SqlServer,exp.sql,exp.parameters) }; db.Aop.OnExecutingChangeSql = (sql, pars) => //可以修改SQL和参数的值 { //sql=newsql //foreach(var p in pars) //修改 return new KeyValuePair<string, SugarParameter[]>(sql,pars); };
只支持实体操作
//增、删、改 前和后 ,DataExecuting 和 DataChangesExecuted 用法一样 //2.1-2.3详细介绍 DataExecuting //前 DataChangesExecuted//后( 5.1.4.159版本才支持 用法和 DataExecuting 一样) //查询完对数据进行加工事件 //2.4有详细介绍 DataExecuted
这个事件可以操作 增(标题2.1) 、改(标题2.2) 和 删(标题2.3)
db.Aop.DataExecuting = (oldValue, entityInfo) => { /*** 列级别事件:插入的每个列都会进事件 ***/ if (entityInfo.PropertyName == "CreateTime"&&entityInfo.OperationType== DataFilterType.InsertByObject) { entityInfo.SetValue(DateTime.Now);//修改CreateTime字段 /*entityInfo有字段所有参数*/ /*oldValue表示当前字段值 等同于下面写法*/ //var value=entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue); /*获取当前列特性*/ //5.1.3.23 + //entityInfo.IsAnyAttribute<特性>() //entityInfo.GetAttribute<特性>() } /*** 行级别事件 :一条记录只会进一次 ***/ if(entityInfo.EntityColumnInfo.IsPrimarykey) { //entityInfo.EntityValue 拿到单条实体对象 } //可以写多个IF }; /***只能是实体插入***/ db.Insertable(T).ExecuteReturnIdentity(); db.Insertable(List<T>).ExecuteReturnIdentity();
这个事件可以操作 增(标题2.1) 、改(标题2.2) 和 删(标题2.3)
db.Aop.DataExecuting = (oldValue, entityInfo) => { /*** 列级别事件 :更新的每一列都会进事件 ***/ if (entityInfo.PropertyName =="UpdateTime" && entityInfo.OperationType == DataFilterType.UpdateByObject) { entityInfo.SetValue(DateTime.Now);//修改UpdateTime字段 /*当前列获取特性*/ //5.1.3.23 + //entityInfo.IsAnyAttribute<特性>() //entityInfo.GetAttribute<特性>() } /*** 行级别事件 :更新一条记录只进一次 ***/ if(entityInfo.EntityColumnInfo.IsPrimarykey) { //entityInfo.EntityValue 拿到单条实体对象 } /*** 根据当前列修改另一列 ***/ //if(当前列逻辑==XXX) //var properyDate = entityInfo.EntityValue.GetType().GetProperty("Date"); //if(properyDate!=null) //properyDate.SetValue(entityInfo.EntityValue,1); //可以写多个IF }; /***实体方式更新***/ db.Updateable(data).ExecuteCommand(); db.Updateable(dataList).ExecuteCommand(); //指定列更追加过滤器(5.1.4.106-Preview19+) db.Updateable(updateObj).UpdateColumns(it=>new {it.Name},true).ExecuteCommand() /***表达式方式更新***/ //新功能 5.1.3.2:表达式更新支持数据过滤器 db.Updateable<Order>() .SetColumns(it => new Order(){ Name="A" } ,appendColumnsByDataFilter:true)//true表式追加过滤器赋值字段 .Where(it=>it.Id==1).ToSqlString()
这个事件可以操作 增(标题2.1) 、改(标题2.2) 和 删(标题2.3)
db.Aop.DataExecuting = (oldValue, entityInfo) => { /*** 删除生效 (只有行级事件) ***/ if (entityInfo.OperationType == DataFilterType.DeleteByObject) { //entityInfo.EntityValue 拿到所有实体对象 } //可以写多个IF } /***只能是实体删除***/ db.Deleteable(List<T>).ExecCommand();//实体集合有效 db.Deleteable(T).ExecCommand();//实体有效
新功能:5.1.2-preview05
//只能是实体查询不能是匿名对象 db.Aop.DataExecuted = (value, entity) => { //只有行级事件 if (entity.Entity.Type == typeof(Order)) { var newValue=entity.GetValue(nameof(Order.Name))+"111"; entity.SetValue(nameof(Order.Name), newValue); } }; //查询出来的值的 name都加上了 111 List<Order> list2 = db.Queryable<Order>().ToList();
2.1、2.2 和 2.4 一起用就可以实现加密和解密字段 或者 自定义类型实现
https://www.donet5.com/Home/Doc?typeId=1205
ORM中唯一支持:触发器、默认值的审计 ,在多家上市公司项目得到实践交付
注意: 5.0.4.4 支持批量操作
Sql执行完后会进该事件,该事件可以拿到更改前记录和更改后记录,执行时间等参数(可以监控表变动)
该功能和 EF Core ChangeTracker 类似
db.Aop.OnDiffLogEvent = it => { //操作前记录 包含: 字段描述 列名 值 表名 表描述 var editBeforeData = it.BeforeData;//插入Before为null,之前还没进库 //操作后记录 包含: 字段描述 列名 值 表名 表描述 var editAfterData = it.AfterData; var sql = it.Sql; var parameter = it.Parameters; var data = it.BusinessData;//这边会显示你传进来的对象 var time = it.Time; var diffType=it.DiffType;//enum insert 、update and delete //Write logic }; db.Insertable(new Student() { Name = "beforeName" }) .EnableDiffLogEvent() //注意需要加上启用日志 .ExecuteReturnIdentity(); db.Updateable<Student>(new Student() { Id = id, CreateTime = DateTime.Now, Name = "afterName", SchoolId = 2 }) .EnableDiffLogEvent(new { title = "update Student", Modular = 1, Operator = "admin" }) //启用并传业务对象参数 .ExecuteCommand(); db.Deleteable<Student>(id) .EnableDiffLogEvent("删除学生") //启用传字符串业务参数 .ExecuteCommand();
只获取差异部分
https://www.donet5.com/ask/9/23905
升级到:5.1.4.73-preview05
//程序启动时注册 StaticConfig.CompleteInsertableFunc= StaticConfig.CompleteUpdateableFunc= StaticConfig.CompleteDeleteableFunc = it => //it是具体的对象Updateable<T>等是个object { //反射的方法可能多个就需要用GetMethods().Where var method = it.GetType().GetMethod("EnableDiffLogEvent"); method.Invoke(it,new object[] { null }); //技巧: //可以定义一个接口只要是这个接口的才走这个逻辑 //if(db.GetType().GenericTypeArguments[0].GetInterfaces().Any(it=>it==typeof(IDiff)) //可以根据类型写if //if(x.GetType().GenericTypeArguments[0] = typeof(Order)) { } }; //注册完就 //Insertable、Updateable和Deleteable就会自动调用EnableDiffLogEvent() //不需一个一个写
这么改你所有操生成的sql表名前面就加了前缀 select * from "public"."表名"
return new SqlSugarClient(new ConnectionConfig() { DbType = SqlSugar.DbType.PostgreSQL, ConnectionString = Config.ConnectionString, InitKeyType = InitKeyType.Attribute, IsAutoCloseConnection = true, ConfigureExternalServices=new ConfigureExternalServices() { EntityNameService = (type, entity) => { entity.DbTableName = "public." + entity.DbTableName; } } });
上面只修改了表,如果我要表和列都修改呢
EntityNameService = (type, entity) => { //修改表 }, EntityService = (type, column) => { //修改列 }
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { DbType = DbType.SqlServer, ConnectionString = Config.ConnectionString, InitKeyType = InitKeyType.Attribute, IsAutoCloseConnection = true }); db.Aop.OnLogExecuted = (sql, p) => { //执行时间超过1秒 if (db.Ado.SqlExecutionTime.TotalSeconds > 1) { //代码CS文件名 var fileName= db.Ado.SqlStackTrace.FirstFileName; //代码行数 var fileLine = db.Ado.SqlStackTrace.FirstLine; //方法名 var FirstMethodName = db.Ado.SqlStackTrace.FirstMethodName; //db.Ado.SqlStackTrace.MyStackTraceList[1].xxx 获取上层方法的信息 } //相当于EF的 PrintToMiniProfiler };
注意:事件不要写错了,写错可能会出现负数,要执行后事件,不能是执行前
/***注意***/ //如果你用的 GetConnectionScope或者 GetConnectionScopeWithAttr AOP也应该用 GetConnectionScope //如果你用的 GetConnection或者 GetConnectionWithAttr AOP也应该用 GetConnectionScope SqlSugarClient Db= new SqlSugarClient(new ConnectionConfig(){ ConnectionString = "连接符字串", DbType = DbType.SqlServer, IsAutoCloseConnection = true}, db=>{ //也可以这里面循环 db.GetConnection("1").Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine("执行1库"+sql); }; db.GetConnection("0").Aop.OnLogExecuting = (sql, pars) => { Console.WriteLine("执行0库"+sql); }; });
这个功能相当于替换ADO执行方法,已经超出来AOP的范畴
https://www.donet5.com/Home/Doc?typeId=2413
https://www.donet5.com/home/Doc?typeId=1205
//建一个扩展类 public static class SqlsugarSetup { public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration configuration, string dbName = "db_master") { SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig() { DbType = SqlSugar.DbType.MySql, ConnectionString = configuration.GetConnectionString(dbName), IsAutoCloseConnection = true, }, db => { //技巧:拿到非ORM注入对象 var serviceBuilder = services.BuildServiceProvider(); var log= serviceBuilder.GetService<类>(); }); services.AddSingleton<ISqlSugarClient>(sqlSugar);//这边是SqlSugarScope用AddSingleton } } //Startup.cs文件添加下面代码 services.AddSqlsugarSetup(Configuration); //业务类和仓储对象不能用单例(只有SqlSugarScope注入单例其他不要单例)
升级到:5.1.4.73-preview05
可以针对Queryable Insertable Updateable Deleteable ISqlSugarClient对象创建完得行全局修改
CompleteQueryableFunc:Queryable创建完事件
CompleteInsertableFunc: Insertable创建完事件
CompleteUpdateableFunc: Updateable创建完事件
CompleteDeleteableFunc: Deleteable创建完事件
CompleteDbFunc: ISqlSugarClient创建完事件
写个用例:
//程序启动时注册 StaticConfig.CompleteInsertableFunc= it => //it是具体的对象Insertable<T>等是个object { //反射的方法可能多个就需要用GetMethods().Where var method = it.GetType().GetMethod("EnableDiffLogEvent"); method.Invoke(it,new object[] { null }); //技巧: //可以定义一个接口只要是这个接口的才走这个逻辑 //if(db.GetType().GenericTypeArguments[0].GetInterfaces().Any(it=>it==typeof(IDiff)) }; //注册完就自动调用.EnableDiffLogEvent() db.Insertable(list).Execommand(); //等同于 // db.Insertable(list).EnableDiffLogEvent().Execommand();
使用全局注入AOP
//程序启动时注册 StaticConfig.CompleteDbFunc=db=> { db.Aop.xxx=xxx }
2016 © donet5.comApache Licence 2.0