日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

[开源] .Net ORM FreeSql 1.10.0 稳步向前

發布時間:2023/12/4 asp.net 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [开源] .Net ORM FreeSql 1.10.0 稳步向前 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

寫在開頭

FreeSql 是 .NET 開源生態下的 ORM 輪子,轉眼快兩年了,說真的開源不容易(只有經歷過才明白)。今天帶點干貨和濕貨給大家,先說下濕貨。

認識我的人,知道 CSRedisCore 是我寫的另外一個開源組件,這個項目是 2016 年從 ctstone/csredis 項目 clone 到自己工作的項目中,修改源碼經過一年多生產考驗,于 2017 年發布開源 https://github.com/2881099/csredis

ctstone/csredis 項目于 2014 年停止了更新,到我手里完善的功能如下:

  • 連接池

  • 哨兵高可用

  • 集群

  • redis 2.8 以上的版本命令補充,包括 Geo、Stream

  • 通訊協議 bug 修復

暫時想到的只有這些,之后可能再補充。FreeSql 文章標題為什么要來說 csredis?

這兩年的時間里 95% 精力都用在了 FreeSql 上面, 5400+ 單元測試、支持十幾種數據庫適配,渣男辜負了 csredis 這個項目。最近一個多月開源圈子的奇葩事接二連三,居然有人跑去 ctstone/csredis 原作者的 issues 告我的狀,這個告狀的人還是 NOPI 原作者,因為當初他自己不維護 NPOI .NET Core 版本了,社區有好人把 .NET Core 版本測試做好了開源(dotnetcore/NPOI),告狀的人很真心厲害,已經成功把 nuget.org/dotnetcore.npoi 整下架了。

他并沒有得到滿足,之后開始針對整個 NCC 社區成員,包括我。

  • 他去了 sqlsugar issues 發表,說要找出 FreeSql 抄襲 sqlsugar 的證據

  • 他又去 fur issues 發表聲援,說我黑他

  • 他還去 csredis 原作者 issues 發布內容,企圖告我的狀

并不是人人都像你一樣,強迫要求下游項目“歸檔”、“制裁”,試問 mysql 可以要求 mariadb 歸檔?針對 NCC 組織還是針對我本人?CSRedisCore 并不在 NCC 開源組織下!!!

幾天月前我已經開始了新的 redis .NET 開源組件庫的編寫,完全自主的看你能上哪里告狀。有了這么長時間的 csredis 經驗,重新寫一個能避免很多問題,設計也會更好,后面我會花大部分時間做新項目,這便是今天帶來的濕貨,敬請期待發布!~!

入戲準備

2018 年 12 月份開發 FreeSql 到現在,2200 顆星,500 Issues,200K 包下載量。說明還是有開發者關注和喜愛,只要有人關注,就不會停更不修 BUG 一說。大家有興趣可以看看更新記錄,看看我們的代碼提交量,5400+ 單元測試不說非常多,個人覺得已經超過很多國產項目。

23個月了,FreeSql 還活著,而且生命力頑強見下圖:

年底發布 2.0 版本正在收集需求中(歡迎前去 issues 誠意登記),本文將介紹在過去的幾個月完成的一些有意義的功能介紹。

FreeSql 是 .Net ORM,能支持 .NetFramework4.0+、.NetCore、Xamarin、XAUI、Blazor、以及還有說不出來的運行平臺,因為代碼綠色無依賴,支持新平臺非常簡單。目前單元測試數量:5400+,Nuget下載數量:200K+,源碼幾乎每天都有提交。值得高興的是 FreeSql 加入了 ncc 開源社區:https://github.com/dotnetcore/FreeSql,加入組織之后社區責任感更大,需要更努力做好品質,為開源社區出一份力。

QQ群:4336577(已滿)、8578575(在線)、52508226(在線)

為什么要重復造輪子?

FreeSql 主要優勢在于易用性上,基本是開箱即用,在不同數據庫之間切換兼容性比較好。作者花了大量的時間精力在這個項目,肯請您花半小時了解下項目,謝謝。

FreeSql 整體的功能特性如下:

  • 支持 CodeFirst 對比結構變化遷移;

  • 支持 DbFirst 從數據庫導入實體類;

  • 支持 豐富的表達式函數,自定義解析;

  • 支持 批量添加、批量更新、BulkCopy;

  • 支持 導航屬性,貪婪加載、延時加載、級聯保存;

  • 支持 讀寫分離、分表分庫,租戶設計;

  • 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達夢/神通/人大金倉/MsAccess Ado.net 實現包,以及 Odbc 的專門實現包;

干貨來了

1.5.0 -> 1.10.0 更新的重要功能如下:

一、增加 Firebird 數據庫實現;

二、增加 人大金倉/神通 數據庫的訪問支持;

三、增加 GlobalFilter.ApplyIf 創建動態過濾器;

四、增加 ISelect.InsertInto 將查詢轉換為 INSERT INTO t1 SELECT ... FROM t2 執行插入;

五、增加 IncludeMany(a => a.Childs).ToList(a => new { a.Childs }) 指定集合屬性返回;

六、增加 $"{a.Code}_{a.Id}" lambda 解析;

七、增加 lambda 表達式樹解析子查詢 ToList + string.Join() 產生 類似 group_concat 的效果;

八、增加 SqlExt 常用開窗函數的自定義表達式解析;

九、增加 ISelect/IInsert/IUpdate/IDelete CommandTimeout 方法設置命令超時;

十、完善 WhereDynamicFilter 動態過濾查詢;

十一、增加 BeginEdit/EndEdit 批量編輯數據的功能;

十二、增加 父子表(樹表)遞歸查詢、刪除功能;

FreeSql 使用非常簡單,只需要定義一個 IFreeSql 對象即可:

static?IFreeSql?fsql?=?new?FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql,?connectionString).UseAutoSyncStructure(true)?//自動同步實體結構到數據庫.Build();?//請務必定義成?Singleton?單例模式

增加 Firebird 數據庫實現;

它的體積比前輩Interbase縮小了幾十倍,但功能并無閹割。為了體現Firebird短小精悍的特色,開發小組在增加了超級服務器版本之后,又增加了嵌入版本,最新版本為2.0。Firebird的嵌入版有如下特色:

1、數據庫文件與Firebird網絡版本完全兼容,差別僅在于連接方式不同,可以實現零成本遷移。 2、數據庫文件僅受操作系統的限制,且支持將一個數據庫分割成不同文件,突破了操作系統最大文件的限制,提高了IO吞吐量。 3、完全支持SQL92標準,支持大部分SQL-99標準功能。 4、豐富的開發工具支持,絕大部分基于Interbase的組件,可以直接使用于Firebird。 5、支持事務、存儲過程、觸發器等關系數據庫的所有特性。 6、可自己編寫擴展函數(UDF)。 7、firebird其實并不是純粹的嵌入式數據庫,embed版只是其眾多版本中的一個。不過做的也很小,把幾個dll加起來才不到5M,但是它支持絕大部份SQL92與SQL99標準

嵌入式,等于無需安裝的本地數據庫,歡迎體驗!~~


增加 人大金倉/神通 數據庫的訪問支持

天津神舟通用數據技術有限公司(簡稱“神舟通用公司”),隸屬于中國航天科技集團(CASC)。是國內從事數據庫、大數據解決方案和數據挖掘分析產品研發的專業公司。公司獲得了國家核高基科技重大專項重點支持,是核高基專項的牽頭承擔單位。自1993年在航天科技集團開展數據庫研發以來,神通數據庫已歷經27年的發展歷程。公司核心產品主要包括神通關系型數據庫、神通KStore海量數據管理系統、神通商業智能套件等系列產品研發和市場銷售。基于產品組合,可形成支持交易處理、MPP數據庫集群、數據分析與處理等解決方案,可滿足多種應用場景需求。產品通過了國家保密局涉密信息系統、公安部等保四級、軍B +級等安全評測和認證。

北京人大金倉信息技術股份有限公司(以下簡稱“人大金倉”)是具有自主知識產權的國產數據管理軟件與服務提供商。人大金倉由中國人民大學一批最早在國內開展數據庫教學、科研、開發的專家于1999年發起創立,先后承擔了國家“863”、“核高基”等重大專項,研發出了具有國際先進水平的大型通用數據庫產品。2018年,人大金倉申報的“數據庫管理系統核心技術的創新與金倉數據庫產業化”項目榮獲2018年度國家科學技術進步二等獎,產學研的融合進一步助力國家信息化建設。

隨著華為、中興事務,國產數據庫市場相信是未來是趨勢走向,縱觀 .net core 整個圈子對國產神舟通用、人大金倉數據庫的支持幾乎為 0,今天 FreeSql ORM 可以使用 CodeFirst/DbFirst 兩種模式進行開發。

并且聲稱:FreeSql 對各數據庫沒有親兒子一說,除了 MsAcces 其他全部是親兒子,在功能提供方面一碗水端平。

眾所周知 EFCore for oracle 問題多,并且現在才剛剛更新到 3.x,在這樣的背景下,一個國產數據庫更不能指望誰實現好用的 EFCore。目前看來除了 EFCore for sqlserver 我們沒把握完全占優勢,起碼在其他數據庫肯定是我們更接地氣。

使用 FreeSql 訪問人大金倉/神通 數據庫,只需要修改代碼如下即可:

static?IFreeSql?fsql?=?new?FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.ShenTong,?connectionString)?//修改?DataType?設置切換數據庫.UseAutoSyncStructure(true)?//自動同步實體結構到數據庫.Build();?//請務必定義成?Singleton?單例模式

增加 GlobalFilter.ApplyIf 創建動態過濾器;

FreeSql 使用全局過濾器非常簡單,我們的過濾器支持多表查詢、子查詢,只需要設置一次:

public?static?AsyncLocal<Guid>?TenantId?{?get;?set;?}?=?new?AsyncLocal<Guid>();fsql.GlobalFilter.Apply<ISoftDelete>("name1",?a?=>?a.IsDeleted?==?false).ApplyIf<ITenant>("tenant",?()?=>?TenantId.Value?!=?Guid.Empty,?a?=>?a.TenantId?==?TenantId.Value);

上面增加了兩個過濾器,tenant 第二個參數正是增加的功能,當委托條件成立時才會附加過濾器。


增加 ISelect.InsertInto 將查詢轉換為 INSERT INTO t1 SELECT ... FROM t2 執行插入;

int?affrows?=?fsql.Select<Topic>().Limit(10).InsertInto(null,?a?=>?new?Topic2{Title?=?a.Title}); INSERT?INTO?`Topic2`(`Title`,?`Clicks`,?`CreateTime`) SELECT?a.`Title`,?0,?'0001-01-01?00:00:00'? FROM?`Topic`?a? limit?10

注意:因為 Clicks、CreateTime 沒有被選擇,所以使用目標實體屬性 [Column(InsertValueSql = xx)] 設置的值,或者使用目標實體屬性的 c# 默認值。

又一次完善了批量操作數據的功能,之前已經有的功能如下:

  • fsql.InsertOrUpdate 相當于 Merge Into/on duplicate key update

DatabaseFeatures
DatabaseFeatures
MySqlon duplicate key update
達夢merge into
PostgreSQLon conflict do update
人大金倉on conflict do update
SqlServermerge into
神通merge into
Oraclemerge into
MsAccess不支持
Sqlitereplace into


Firebirdmerge into


  • fsql.Insert(數組).ExecuteAffrows() 相當于批量插入

var?t2?=?fsql.Insert(items).ExecuteAffrows(); //INSERT?INTO?`Topic`(`Clicks`,?`Title`,?`CreateTime`)? //VALUES(?Clicks0,??Title0,??CreateTime0),?(?Clicks1,??Title1,??CreateTime1),? //(?Clicks2,??Title2,??CreateTime2),?(?Clicks3,??Title3,??CreateTime3),? //(?Clicks4,??Title4,??CreateTime4),?(?Clicks5,??Title5,??CreateTime5),? //(?Clicks6,??Title6,??CreateTime6),?(?Clicks7,??Title7,??CreateTime7),? //(?Clicks8,??Title8,??CreateTime8),?(?Clicks9,??Title9,??CreateTime9)

當插入大批量數據時,內部采用分割分批執行的邏輯進行。分割規則:


數量參數量
MySql50003000
PostgreSQL50003000
SqlServer10002100
Oracle500999
Sqlite5000999

  • fsql.Insert(數組).ExecuteSqlBulkCopy、ExecutePgCopy、ExecuteMySqlBulkCopy

  • fsql.Update<T>().SetSource(數組).ExecuteAffrows() 相當于批量更新


增加 IncludeMany(a => a.Childs).ToList(a => new { a.Childs }) 指定集合屬性返回;

這個功能實在太重要了,在此之前 IncludeMany 和 ToList(指定字段) 八字不合,用起來有些麻煩。現在終于解決了!!~~

var?t111?=?fsql.Select<Topic>().IncludeMany(a?=>?a.TopicType.Photos).Where(a?=>?a.Id?<=?100).ToList(a?=>?new{a.Id,a.TopicType.Photos,Photos2?=?a.TopicType.Photos});

增加 $"{a.Code}_{a.Id}" lambda 解析;

在之前查詢數據的時候,$"" 這種語法糖神器居然不能使用在 lambda 表達式中,實屬遺憾。現在終于可以了,如下:

var?item?=?fsql.GetRepository<Topic>().Insert(new?Topic?{?Clicks?=?101,?Title?=?"我是中國人101",?CreateTime?=?DateTime.Parse("2020-7-5")?}); var?sql?=?fsql.Select<Topic>().WhereDynamic(item).ToSql(a?=>?new {str?=?$"x{a.Id?+?1}z-{a.CreateTime.ToString("yyyyMM")}{a.Title}{a.Title}" }); Assert.Equal($@"SELECT?concat('x',ifnull((a.`Id`?+?1),?''),'z-',ifnull(date_format(a.`CreateTime`,'%Y%m'),?''),'',ifnull(a.`Title`,?''),'',ifnull(a.`Title`,?''),'')?as1? FROM?`tb_topic`?a? WHERE?(a.`Id`?=?{item.Id})",?sql);

再次說明:都是親兒子,并且都有對應的單元測試,兄臺大可放心用在不同的數據庫中


增加 lambda 表達式樹解析子查詢 ToList + string.Join() 產生 類似 group_concat 的效果;

v1.8.0+ string.Join + ToList 實現將子查詢的多行結果,拼接為一個字符串,如:"1,2,3,4"

fsql.Select<Topic>().ToList(a?=>?new?{id?=?a.Id,concat?=?string.Join(",",?fsql.Select<StringJoin01>().ToList(b?=>?b.Id)) }); //SELECT?a.`Id`,?(SELECT?group_concat(b.`Id`?separator?',')? //????FROM?`StringJoin01`?b)? //FROM?`Topic`?a

該語法,在不同數據庫都作了相應的 SQL 翻譯。


增加 SqlExt 常用的自定義表達式樹解析;

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?:?11groupct1?=?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設計最簡單,我們正是解決它設計簡單,使用復雜的問題。

首先,按照導航屬性的定義,定義好父子屬性:

public?class?Area {[Column(IsPrimary?=?true)]public?string?Code?{?get;?set;?}public?string?Name?{?get;?set;?}public?virtual?string?ParentCode?{?get;?set;?}[Navigate(nameof(ParentCode))]public?Area?Parent?{?get;?set;?}[Navigate(nameof(ParentCode))]public?List<Area>?Childs?{?get;?set;?} }

定義 Parent 屬性,在表達式中可以這樣:

fsql.Select<Area>().Where(a?=>?a.Parent.Parent.Parent.Name?==?"中國").First();

定義 Childs 屬性,在表達式中可以這樣(子查詢):

fsql.Select<Area>().Where(a?=>?a.Childs.AsSelect().Any(c?=>?c.Name?==?"北京")).First();

定義 Childs 屬性,還可以使用【級聯保存】、【貪婪加載】 等等操作。

利用級聯保存,添加測試數據如下:

fsql.Delete<Area>().Where("1=1").ExecuteAffrows(); var?repo?=?fsql.GetRepository<Area>(); repo.DbContextOptions.EnableAddOrUpdateNavigateList?=?true; repo.DbContextOptions.NoneParameter?=?true; repo.Insert(new?Area {Code?=?"100000",Name?=?"中國",Childs?=?new?List<Area>(new[]?{new?Area{Code?=?"110000",Name?=?"北京",Childs?=?new?List<Area>(new[]?{new?Area{?Code="110100",?Name?=?"北京市"?},new?Area{?Code="110101",?Name?=?"東城區"?},})}}) });

功能1:ToTreeList

配置好父子屬性之后,就可以這樣用了:

var?t1?=?fsql.Select<Area>().ToTreeList(); Assert.Single(t1); Assert.Equal("100000",?t1[0].Code); Assert.Single(t1[0].Childs); Assert.Equal("110000",?t1[0].Childs[0].Code); Assert.Equal(2,?t1[0].Childs[0].Childs.Count); Assert.Equal("110100",?t1[0].Childs[0].Childs[0].Code); Assert.Equal("110101",?t1[0].Childs[0].Childs[1].Code);

查詢數據本來是平面的,ToTreeList 方法將返回的平面數據在內存中加工為樹型 List 返回。

功能2:AsTreeCte 遞歸刪除

很常見的無限級分類表功能,刪除樹節點時,把子節點也處理一下。

fsql.Select<Area>().Where(a?=>?a.Name?==?"中國").AsTreeCte().ToDelete().ExecuteAffrows();?//刪除?中國?下的所有記錄

如果軟刪除:

fsql.Select<Area>().Where(a?=>?a.Name?==?"中國").AsTreeCte().ToUpdate().Set(a?=>?a.IsDeleted,?true).ExecuteAffrows();?//軟刪除?中國?下的所有記錄

功能3:AsTreeCte 遞歸查詢

若不做數據冗余的無限級分類表設計,遞歸查詢少不了,AsTreeCte 正是解決遞歸查詢的封裝,方法參數說明:

參數描述
(可選) pathSelector路徑內容選擇,可以設置查詢返回:中國 -> 北京 -> 東城區
(可選) upfalse(默認):由父級向子級的遞歸查詢,true:由子級向父級的遞歸查詢
(可選) pathSeparator設置 pathSelector 的連接符,默認:->
(可選) level設置遞歸層級

通過測試的數據庫:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、達夢、人大金倉

姿勢一:AsTreeCte() + ToTreeList

var?t2?=?fsql.Select<Area>().Where(a?=>?a.Name?==?"中國").AsTreeCte()?//查詢?中國?下的所有記錄.OrderBy(a?=>?a.Code).ToTreeList();?//非必須,也可以使用?ToList(見姿勢二) Assert.Single(t2); Assert.Equal("100000",?t2[0].Code); Assert.Single(t2[0].Childs); Assert.Equal("110000",?t2[0].Childs[0].Code); Assert.Equal(2,?t2[0].Childs[0].Childs.Count); Assert.Equal("110100",?t2[0].Childs[0].Childs[0].Code); Assert.Equal("110101",?t2[0].Childs[0].Childs[1].Code); //?WITH?"as_tree_cte" //?as //?( //?SELECT?0?as?cte_level,?a."Code",?a."Name",?a."ParentCode"? //?FROM?"Area"?a? //?WHERE?(a."Name"?=?'中國')//?union?all//?SELECT?wct1.cte_level?+?1?as?cte_level,?wct2."Code",?wct2."Name",?wct2."ParentCode"? //?FROM?"as_tree_cte"?wct1? //?INNER?JOIN?"Area"?wct2?ON?wct2."ParentCode"?=?wct1."Code" //?) //?SELECT?a."Code",?a."Name",?a."ParentCode"? //?FROM?"as_tree_cte"?a? //?ORDER?BY?a."Code"

姿勢二:AsTreeCte() + ToList

var?t3?=?fsql.Select<Area>().Where(a?=>?a.Name?==?"中國").AsTreeCte().OrderBy(a?=>?a.Code).ToList(); Assert.Equal(4,?t3.Count); Assert.Equal("100000",?t3[0].Code); Assert.Equal("110000",?t3[1].Code); Assert.Equal("110100",?t3[2].Code); Assert.Equal("110101",?t3[3].Code); //執行的?SQL?與姿勢一相同

姿勢三:AsTreeCte(pathSelector) + ToList

設置 pathSelector 參數后,如何返回隱藏字段?

var?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); //?WITH?"as_tree_cte" //?as //?( //?SELECT?0?as?cte_level,?a."Name"?||?'['?||?a."Code"?||?']'?as?cte_path,?a."Code",?a."Name",?a."ParentCode"? //?FROM?"Area"?a? //?WHERE?(a."Name"?=?'中國')//?union?all//?SELECT?wct1.cte_level?+?1?as?cte_level,?wct1.cte_path?||?'?->?'?||?wct2."Name"?||?'['?||?wct2."Code"?||?']'?as?cte_path,?wct2."Code",?wct2."Name",?wct2."ParentCode"? //?FROM?"as_tree_cte"?wct1? //?INNER?JOIN?"Area"?wct2?ON?wct2."ParentCode"?=?wct1."Code" //?) //?SELECT?a."Code"?as1,?a."Name"?as2,?a."ParentCode"?as5,?a.cte_level?as6,?a.cte_path?as7? //?FROM?"as_tree_cte"?a? //?ORDER?BY?a."Code"

更多姿勢...請根據代碼注釋進行嘗試

寫在最后

給 .NET 開源社區貢獻一點力時,希望作者的努力能打動到你,請求正在使用的、善良的您能動一動小手指,把文章轉發一下,讓更多人知道 .NET 有這樣一個好用的 ORM 存在。謝謝了!!

FreeSql 使用最寬松的開源協議 MIT https://github.com/dotnetcore/FreeSql,完全可以商用,文檔齊全。QQ群:4336577(已滿)、8578575(在線)、52508226(在線)

如果你有好的 ORM 實現想法,歡迎給作者留言討論,謝謝觀看!

2.0 版本意見正在登記中:https://github.com/dotnetcore/FreeSql/issues/469

本文作者:FreeSql & CSRedis
本文鏈接:https://www.cnblogs.com/kellynic/p/13855784.html

總結

以上是生活随笔為你收集整理的[开源] .Net ORM FreeSql 1.10.0 稳步向前的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。