我是靠谱客的博主 飘逸汽车,最近开发中收集的这篇文章主要介绍freessql总结添加或修改WithSql父子关系表级联加载WhereCascadeISelect.ToDelete、ISelect.ToUpdate保存多对多数据 SaveMany审计 CURD审计属性值,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

添加或修改

var repo = fsql.GetRepository<T>();
repo.InsertOrUpdate(实体);

 

WithSql

fsql.Select<Topic>()
.WithSql("select * from Topic where clicks > 10")
.Page(1, 10)
.ToList()
//SELECT a.`Id`, a.`Clicks`, a.`CategoryId`, a.`Title`, a.`CreateTime`
//FROM (select * from Topic where clicks > 10) a
//LIMIT 10

 

父子关系表

List<Category> t2 = fsql.Select<Category>.ToTreeList();
List<Category> t3 = fsql.Select<Category>.Where(a => a.Name = "家电").AsTreeCte().ToTreeList();
//v1.6.0 AsTreeCte() 递归CTE查询 家电 下的所有子分类

ToTreeList 查询数据后加工为树型,注意:实体需要配置父子导航属性

//返回 AsTreeCte() 树状层级信息
t4 = fsql.Select<Area>()
.Where(a => a.Name == "中国")
.AsTreeCte(a => a.Name + "[" + a.Code + "]")
.OrderBy(a => a.Code)
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
Assert.Equal(4, t4.Count);
Assert.Equal("100000", t4[0].item.Code);
Assert.Equal("110000", t4[1].item.Code);
Assert.Equal("110100", t4[2].item.Code);
Assert.Equal("110101", t4[3].item.Code);
Assert.Equal("中国[100000]", t4[0].path);
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);

 

级联加载

有设置导航属性关系的(支持一对多、多对多):

fsql.Select<Tag>().IncludeMany(a => a.Goods).ToList();

未设置导航属性关系的,临时指定关系(只支持一对多):

fsql.Select<Goods>().IncludeMany(a => a.Comment.Where(b => b.TagId == a.Id));

只查询每项子集合的前几条数据,避免像EfCore加载所有数据导致IO性能低下(比如某商品下有2000条评论):

fsql.Select<Goods>().IncludeMany(a => a.Comment.Take(10));

在 Dto 上做映射 IncludeMany:

//定义临时类,也可以是 Dto 类
class Dto {
public int TypeId { get; set; }
public List<Goods > GoodsList { get; set; }
}
//查询 Goods 商品表,分类1、分类2、分类3 各10条数据
var dto = new [] { 1,2,3 }.Select(a => new Dto { TypeId = a }).ToList();
dto.IncludeMany(d => d.GoodsList.Take(10).Where(gd => gd.TypeId == d.TypeId));
//执行后,dto 每个元素.Vods 将只有 10条记录

查询子集合表的部分字段,避免子集合字段过多的问题:

fsql.Select<Tag>().IncludeMany(a => a.Goods.Select(b => new Goods { Id = b.Id, Title = b.Title }));
//只查询 goods 表 id, title 字段,再作填充

 

WhereCascade

多表查询时,像isdeleted每个表都给条件,挺麻烦的。WhereCascade使用后生成sql时,所有表都附上这个条件。

如:

fsql.Select<t1>()
.LeftJoin<t2>(...)
.WhereCascade(x => x.IsDeleted == false)
.ToList();

OneToMany 级联保存

方式一:完整保存,对比表已存在的数据,计算出添加、修改、删除执行

var repo = fsql.GetRepository<T>();
repo.Insert(item);
repo.SaveMany(item, "Childs");

方式二:追加保存,不删除表已存在的数据

var repo = fsql.GetRepository<T>();
repo.DbContextOptions.EnableAddOrUpdateNavigateList = true; //需要手工开启
repo.Insert(item);

ISelect.ToDelete、ISelect.ToUpdate

默认 IDelete 不支持导航对象,多表关联等。ISelect.ToDelete 可将查询转为删除对象,以便支持导航对象或其他查询功能删除数据,如下:

fsql.Select<T1>().Where(a => a.Options.xxx == 1).ToDelete().ExecuteAffrows();

注意:此方法不是将数据查询到内存循环删除,上面的代码产生如下 SQL 执行:

DELETE FROM `T1` WHERE id in (select a.id from T1 a left join Options b on b.t1id = a.id where b.xxx = 1)

 

 

保存多对多数据 SaveMany

之前:

FreeSql.DbContext 和 仓储实现,已经实现了联级保存功能,联级保存功能可实现保存对象的时候,将其【OneToMany】、【ManyToMany】导航属性集合也一并保存。

全局关闭:

fsql.SetDbContextOptions(opt => opt.EnableAddOrUpdateNavigateList = false);

局部关闭:

var repo = fsql.GetRepository<T>();
repo.DbContextOptions.EnableAddOrUpdateNavigateList = false;

 

审计 CURD

如果因为某个 sql 骚操作耗时很高,没有一个相关的审计功能,排查起来可以说无从下手。

FreeSql 支持简单的类似功能:

fsql.Aop.CurdAfter += (s, e) => {
if (e.ElapsedMilliseconds > 200) {
//记录日志
//发送短信给负责人
}
};

 

审计属性值

实现插入/更新时统一处理某些值,比如某属性的雪花算法值、创建时间值、甚至是业务值。

fsql.Aop.AuditValue += (s, e) => {
if (e.Column.CsType == typeof(long)
&& e.Property.GetCustomAttribute<SnowflakeAttribute>(false) != null
&& e.Value?.ToString() == 0)
e.Value = new Snowflake().GetId();
};
class Order {
[Snowflake]
public long Id { get; set; }
//...
}

 

 

自定义类型映射(MapType)

class EnumTestMap {
public Guid id { get; set; }
[Column(MapType = typeof(string))]
public ToStringMapEnum enum_to_string { get; set; }
[Column(MapType = typeof(string))]
public ToStringMapEnum? enumnullable_to_string { get; set; }
[Column(MapType = typeof(int))]
public ToStringMapEnum enum_to_int { get; set; }
[Column(MapType = typeof(int?))]
public ToStringMapEnum? enumnullable_to_int { get; set; }
[Column(MapType = typeof(string))]
public BigInteger biginteger_to_string { get; set; }
[Column(MapType = typeof(string))]
public BigInteger? bigintegernullable_to_string { get; set; }
}
public enum ToStringMapEnum { 中国人, abc, 香港 }

 

 

服务器时间(ServerTime)

class Topic {
[Column(ServerTime = DateTimeKind.Utc, CanUpdate = false)]
public DateTime CreateTime { get; set; }
[Column(ServerTime = DateTimeKind.Utc)]
public DateTime UpdateTime { get; set; }
}

 

 

值对象映射成 typeof(string),安装扩展包:

dotnet add package FreeSql.Extensions.JsonMap

fsql.UseJsonMap(); //开启功能
class TestConfig {
public int clicks { get; set; }
public string title { get; set; }
}
[Table(Name = "sysconfig")]
public class S_SysConfig {
[Column(IsPrimary = true)]
public string Name { get; set; }
[JsonMap]
public TestConfig Config { get; set; }
}

 

字段位置(Position)

适用场景:当实体类继承时,CodeFirst创建表的字段顺序可能不是想要的,通过该特性可以设置顺序。

创建表时指定字段位置,如:[Column(Position = 1],可为负数即反方向位置;

 

禁用迁移

IFreeSql.CodeFirst.IsAutoSyncStructure 可设置全局【自动迁移结构】功能,也可通过 FreeSqlBuilder.UseAutoSyncStructure(true) 创建 IFreeSql 的时候设置功能。

当【实体类】对应的是数据库【视图】或者其他时,可通过 [Table(DisableSyncStructure = true)] 禁用指定的实体迁移操作。

[Table(DisableSyncStructure = true)]
class ModelDisableSyncStructure {
[Column(IsPrimary = false)]
public int pkid { get; set; }
}

最后

以上就是飘逸汽车为你收集整理的freessql总结添加或修改WithSql父子关系表级联加载WhereCascadeISelect.ToDelete、ISelect.ToUpdate保存多对多数据 SaveMany审计 CURD审计属性值的全部内容,希望文章能够帮你解决freessql总结添加或修改WithSql父子关系表级联加载WhereCascadeISelect.ToDelete、ISelect.ToUpdate保存多对多数据 SaveMany审计 CURD审计属性值所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(30)

评论列表共有 0 条评论

立即
投稿
返回
顶部