FreeSql 以 MIT 开源协议托管于 github:https://github.com/2881099/FreeSql
FreeSql AOP 已有的功能介绍,未来为会根据用户需求不断增强。
审计 CRUD
马云说过,996是修福报。对于多数程序员来说,加班是好事。。。起码不是闲人,不会下岗。
当如果因为某个 sql 骚操作耗时很高,没有一个相关的审计功能,排查起来可以说无从下手,福报与你紧紧相随(哈哈)。
FreeSql 支持简单的类似功能:
fsql.Aop.CurdAfter = (s, e) => {
if (e.ElapsedMilliseconds > 200) {
//记录日志
//发送短信给负责人
}
};
是的,只需要一个事件,就可以对全局起到作用。
除了 CurdAfter,还有一个 CurdBefore (在执行 sql 之前触发)。
审计属性值
实现插入/更新时统一处理某些值,比如某属性的雪花算法值、创建时间值、甚至是业务值。
fsql.Aop.AuditValue += (s, e) => {
if (e.Column.CsType == typeof(long)
&& e.Property.GetCustomAttribute(false) != null
&& e.Value?.ToString() == 0)
e.Value = new Snowflake().GetId();
};
class Order {
[Snowflake]
public long Id { get; set; }
//...
}
当属性的类型是 long,并且标记了 [Snowflake],并且当前值是 0,那么在插入/更新时它的值将设置为雪花id值。
说明:SnowflakeAttribute 是使用者您来定义,new Snowflake().GetId() 也是由使用者您来实现
如果命名规范,可以在 aop 里判断,if (e.Property.Name == "createtime") e.Value = DateTime.Now;
审计迁移脚本
FreeSql 自带迁移功能,那么迁移的 SQL 语句长啥样,你可能会好奇。
比如创建表时;
比如添加字段时;
比如修改表名、修改字段名时;
又比如字段类型更改之后时;
这些操作在 FreeSql.CodeFirst 实现下基本不需要理会,而且我们只推荐在开发环境使用自动迁移的功能,正式环境可使用其他工具替代此操作。
但我们仍然可能需要对项目做完整的日志记录。
fsql.Aop.SyncStructureBefore、fsql.Aop.SyncStructureAfter 这两个事件将排上用场。
自定义实体特性
比如项目内已经使用了其它 orm,如 efcore,这样意味着实体中可能存在 [Key],但它与 FreeSql [Column(IsPrimary = true] 不同。
Q: FreeSql 实体特性为啥这么别扭?
A: 为了考虑一致性用法,全部封装在 ColumnAttribute 下,这样用户使用起来,不用到处 using 或者 回忆特性应该用哪个名字,如自增 [Column(IsIdentity = true)] 即可。
FreeSql 提供 AOP 自定义特性功能,实现与多个 orm 共同拥有一套实体特性,可避免重复定义特性。
fsql.Aop.ConfigEntity = (s, e) => {
var attr = e.EntityType.GetCustomAttributes(
typeof(System.ComponentModel.DataAnnotations.Schema.TableAttribute), false).FirstOrDefault()
as System.ComponentModel.DataAnnotations.Schema.TableAttribute;
if (attr != null)
e.ModifyResult.Name = attr.Name; //表名
};
fsql.Aop.ConfigEntityProperty = (s, e) => {
if (e.Property.GetCustomAttributes(
typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false).Any())
e.ModifyResult.IsPrimary = true; //主键
};
就这样,FreeSql 的实体特性就可以和 EFCore 那样设定了。其他自增、乐观锁等,依葫芦画瓢便是。
自定义表达式
FreeSql 内部表达式支持非常丰富,对各大数据库的兼容度也做得很好。
有关表达式支持到的程度,可点击查看详细wiki:https://github.com/2881099/FreeSql/wiki/%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%87%BD%E6%95%B0
即便如此丰富,也仍然无法满足用户需求,FreeSql 对外开放了自定义表达式解析接口:
fsql.Aop.ParseExpression = (s, e) => {
if (e.Expression.NodeType == Call && e.Expression.Name == "get_Item")
e.Result = "1111";
};
这个解析有点复杂,当 e.Expression 很复杂的时候,我们还提供了 e.FreeParse 方法,使用它相当于调用 FreeSql 内置表达式解析引擎,辅助您进行解析。
Aop.Where
FreeSql 提供的 ISelect、IDelete、IUpdate 三大对象,都可以使用 .Where(lambda) 操作,也可以是 .Where(sql) 操作。
Aop.Where 的定位是可拦截 Where 条件。
fsql.Aop.Where = (s, e) => {
if (e.Parameter[0]?.ToString() == "1")
e.IsCancel = true;
};
Aop.ToList
监控 ToList 返回的的数据,用于拦截重新装饰。
所有通过 FreeSql.Select 查询返回的时候,都可以在这个事件上进行重新装饰。
系列文章导航
(一)入门
(二)自动迁移实体
(三)实体特性
(四)实体特性 Fluent Api
(五)插入数据
(六)批量插入数据
(七)插入数据时忽略列
(八)插入数据时指定列
(九)删除数据
(十)更新数据
(十一)更新数据 Where
(十二)更新数据时指定列
(十三)更新数据时忽略列
(十四)批量更新数据
(十五)查询数据
(十六)分页查询
(十七)联表查询
(十八)导航属性
(十九)多表查询
(二十)多表查询 WhereCascade
(二十一)查询返回数据
(二十二)Dto 映射查询
(二十三)分组、聚合
(二十四)Linq To Sql 语法使用介绍
(二十五)延时加载
(二十六)贪婪加载 Include、IncludeMany、Dto、ToList
(二十七)将已写好的 SQL 语句,与实体类映射进行二次查询
(二十八)事务
(二十九)Lambda 表达式
(三十)读写分离
(三十一)分区分表
(三十二)Aop
(三十三)CodeFirst 类型映射
(三十四)CodeFirst 迁移说明
(三十五)CodeFirst 自定义特性