SqlExt.cs 定义了一些常用的表达式树解析,如下:
fsql.Select<T1, T2>() .InnerJoin((a, b) => b.Id == a.Id) .ToList((a, b) => new { Id = a.Id, EdiId = b.Id, over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue(), case1 = SqlExt.Case() .When(a.Id == 1, 10) .When(a.Id == 2, 11) .When(a.Id == 3, 12) .When(a.Id == 4, 13) .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End()) .End(), //这里因为复杂才这样,一般使用三元表达式即可:a.Id == 1 ? 10 : 11 groupct1 = SqlExt.GroupConcat(a.Id).Distinct().OrderBy(b.EdiId).Separator("_").ToValue() });本功能利用 FreeSql 自定义解析实现常用表达式树解析,欢迎 PR 补充
增加 ISelect/IInsert/IUpdate/IDelete CommandTimeout 方法设置命令超时;现在每条 crud 都可以设置命令执行的超时值,如下:
fsql.Insert<items).CommandTimeout(60).ExecuteAffrows(); fsql.Delete<T>().Where(...).CommandTimeout(60).ExecuteAffrows(); fsql.Update<T>() .Set(a => a.Clicks + 1) .Where(...) .CommandTimeout(60).ExecuteAffrows(); fsql.Select<T>().Where(...).CommandTimeout(60).ToList(); 完善 WhereDynamicFilter 动态过滤查询是否见过这样的高级查询功能,WhereDynamicFilter 在后端可以轻松完成这件事情,前端根据 UI 组装好对应的 json 字符串传给后端就行,如下:
DynamicFilterInfo dyfilter = JsonConvert.DeserializeObject<DynamicFilterInfo>(@" { ""Logic"" : ""Or"", ""Filters"" : [ { ""Field"" : ""Code"", ""Operator"" : ""NotContains"", ""Value"" : ""val1"", ""Filters"" : [{ ""Field"" : ""Name"", ""Operator"" : ""NotStartsWith"", ""Value"" : ""val2"" }] }, { ""Field"" : ""Parent.Code"", ""Operator"" : ""Equals"", ""Value"" : ""val11"", ""Filters"" : [{ ""Field"" : ""Parent.Name"", ""Operator"" : ""Contains"", ""Value"" : ""val22"" }] } ] }"); fsql.Select<VM_District_Parent>().WhereDynamicFilter(dyfilter).ToList(); //SELECT a.""Code"", a.""Name"", a.""ParentCode"", a__Parent.""Code"" as4, a__Parent.""Name"" as5, a__Parent.""ParentCode"" as6 //FROM ""D_District"" a //LEFT JOIN ""D_District"" a__Parent ON a__Parent.""Code"" = a.""ParentCode"" //WHERE (not((a.""Code"") LIKE '%val1%') AND not((a.""Name"") LIKE 'val2%') OR a__Parent.""Code"" = 'val11' AND (a__Parent.""Name"") LIKE '%val22%')ISelect.WhereDynamicFilter 方法实现动态过滤条件(与前端交互),支持的操作符:
Contains/StartsWith/EndsWith/NotContains/NotStartsWith/NotEndsWith:包含/不包含,like '%xx%',或者 like 'xx%',或者 like '%xx'
Equal/NotEqual:等于/不等于
GreaterThan/GreaterThanOrEqual:大于/大于等于
LessThan/LessThanOrEqual:小于/小于等于
Range:范围查询
DateRange:日期范围,有特殊处理 value[1] + 1
Any/NotAny:是否符合 value 中任何一项(直白的说是 SQL IN)
增加 BeginEdit/EndEdit 批量编辑数据的功能;场景:winform 加载表数据后,一顿添加、修改、删除操作之后,点击【保存】
[Fact] public void BeginEdit() { fsql.Delete<BeginEdit01>().Where("1=1").ExecuteAffrows(); var repo = fsql.GetRepository<BeginEdit01>(); var cts = new[] { new BeginEdit01 { Name = "分类1" }, new BeginEdit01 { Name = "分类1_1" }, new BeginEdit01 { Name = "分类1_2" }, new BeginEdit01 { Name = "分类1_3" }, new BeginEdit01 { Name = "分类2" }, new BeginEdit01 { Name = "分类2_1" }, new BeginEdit01 { Name = "分类2_2" } }.ToList(); repo.Insert(cts); repo.BeginEdit(cts); //开始对 cts 进行编辑 cts.Add(new BeginEdit01 { Name = "分类2_3" }); cts[0].Name = "123123"; cts.RemoveAt(1); Assert.Equal(3, repo.EndEdit()); } class BeginEdit01 { public Guid Id { get; set; } public string Name { get; set; } }上面的代码 EndEdit 方法执行的时候产生 3 条 SQL 如下:
INSERT INTO "BeginEdit01"("Id", "Name") VALUES('5f26bf07-6ac3-cbe8-00da-7dd74818c3a6', '分类2_3') UPDATE "BeginEdit01" SET "Name" = '123123' WHERE ("Id" = '5f26bf00-6ac3-cbe8-00da-7dd01be76e26') DELETE FROM "BeginEdit01" WHERE ("Id" = '5f26bf00-6ac3-cbe8-00da-7dd11bcf54dc')提醒:该操作只对变量 cts 有效,不是针对全表对比更新。
增加 父子表(树表)递归查询、删除功能;无限级分类(父子)是一种比较常用的表设计,每种设计方式突出优势的同时也带来缺陷,如:
方法1:表设计中只有 parent_id 字段,困扰:查询麻烦(本文可解决);
方法2:表设计中冗余子级id便于查询,困扰:添加/更新/删除的时候需要重新计算;
方法3:表设计中存储左右值编码,困扰:同上;
方法1设计最简单,我们正是解决它设计简单,使用复杂的问题。