1. 程式人生 > >喜歡 Dapper 的朋友看過來,送一份厚禮

喜歡 Dapper 的朋友看過來,送一份厚禮

## 寫在開頭 眾所周知 Dapper 是 .NET 下最輕最快的 ORM,它是喜歡寫 SQL 碼農的福音,相對於 SqlHelper 它更加方便,據統計 10個 .NETer 有 9個 用過 Dapper。 由於 .NET 環境的特殊,對 Lambda 表示式樹的喜愛,於是市面上有很多出現了基於 Dapper 的輕量級 ORM,它們幾乎都有共同特點,讓 Dapper 支援 Lambda 表示式樹,寫起來順暢如流水。 今天介紹一款本身功能已經很強大的 ORM,他提供一個隱藏得比較深的 API 功能,使用起來和 Dapper 沒什麼兩樣。 ## 瞭解 Lambda 表示式樹 這要先從 Lambda 表示式開始說起,詞語中少了一個“樹”字,差別甚大。 表示式,如下各種語法糖騷操作,產生的 IL 一模一樣: ```c# //使用C# 2.0中的匿名方法獲取字串長度 Func strLength = delegate(string str) { return str.Length; }; Console.WriteLine(strLength("Hello World!")); //使用Lambda表示式 //(顯式型別引數列表)=> {語句},lambda表示式最冗長版本 strLength = (string str) => { return str.Length; }; Console.WriteLine(strLength("Hello World!")); //單一表達式作為主體 //(顯式型別引數列表)=> 表示式 strLength = (string str) => str.Length; Console.WriteLine(strLength("Hello World!")); //隱式型別的引數列表 //(隱式型別引數列表)=> 表示式 strLength = (str) => str.Length; Console.WriteLine(strLength("Hello World!")); //單一引數的快捷語法 //引數名 => 表示式 strLength = str => str.Length; Console.WriteLine(strLength("Hello World!")); ``` 而表示式樹呢,程式碼寫起來跟表示式差不多,如下: ```c# Expression> strLength = str => str.Length; ``` > 表示式樹不支援程式碼塊(花括號) 力求書寫簡單,一般情況我們都是這樣寫的,雖然它和表示式程式碼寫起來幾乎一樣,但是返回值和表示式不一樣,多了一個泛型 Expression<>。 表示式樹也稱表示式目錄樹,將程式碼以一種抽象的方式表示成一個物件樹,樹中每個節點本身都是一個表示式。表示式樹不是可執行程式碼,它是一種資料結構。它是程式碼在編譯期間將編寫的程式碼轉換成一個樹結構,以便後續進行逆向解析。 > 如上:(strLength.Body as MemberExpression).Member.Name 可以得到值 "Length" 由於表示式樹可逆向解析的特點,近十年來 EF 是一直是帶頭大哥,國產每年都要整出好幾個 ORM,大部分都是基於表示式樹解析做的。 ## 表示式樹解析 .NET 技術文章從來不缺少表示式樹解析的這類文章,有興趣的可以百度搜索一下,很多很多,但是想做完美可不是件簡單事。 FreeSql 在表示式樹解析上做了下足了工夫,舉例: 1、子表 in 查詢 ```c# .Where(a => fsql.Select().ToList(b => b.Id).Contains(a.Id)) //WHERE a.Id in (select id from t) ``` 2、子表 exists 查詢 ```c# .Where(a => fsql.Select().Any(b => b.Id == a.Id)) //WHERE exists(select 1 from t where Id = a.Id) ``` 3、日期格式化 ```c# ToList(a => a.CreateTime.ToString("HH:mm:ss")) //date_format(a.`CreateTime`, '%H:%i:%s') ``` 4、開窗函式 ```c# ToList(a => SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue()) //rank() over(order by a.Id, b.EdiId desc) ``` 5、Join 子表 ```c# ToList(a => string.Join(",", fsql.Select().ToList(b => b.Id))) //(SELECT group_concat(b.`Id` separator ',') FROM `StringJoin01` b) ``` 這些特性在不同的資料庫,都需要做相應適配實現,FreeSql 還支援對導航屬性的表示式樹解析,說這些只想證明做到細緻真的不容易。 與其自己造著麻煩,不如直接拿來主義使用? ## Ado.Net 擴充套件實現 與其自己造著麻煩,不如直接拿來主義使用?FreeSql 提供了一種非主打的 API 使用習慣,使用起來跟 Dapper 沒什麼區別。 支援 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達夢/神通/人大金倉/翰高/MsAccess 十多種資料庫適配,支援 Ado.net/Odbc,並且支援 .NetFramework 4.0 平臺、.NET5.0、.NET Core2.1 + 平臺。 第一步:以資料庫 SqlServer 訪問為例,只需要安裝已經劃分好的小包: ```bash dotnet add packages FreeSql.Provider.SqlServer ``` or ```bash Install-Package FreeSql.Provider.SqlServer ``` 第二步:建立實體類 ```c# class TestConnectionExt { public Guid id { get; set; } public string title { get; set; } public DateTime createTime { get; set; } = DateTime.Now; } ``` 第三步:開始 CRUD ```c# using (var conn = new SqlConnection(connectString)) { var list = conn.Select().Where(a => a.id == item.id).ToList(); } using (var conn = new SqlConnection(connectString)) { var item = new TestConnectionExt { title = "testinsert" }; var affrows = conn.Insert(item).ExecuteAffrows(); } using (var conn = new SqlConnection(connectString)) { var affrows = conn.Update() .Where(a => a.Id == xxx) .Set(a => a.title, "testupdated") .ExecuteAffrows(); } using (var conn = new SqlConnection(connectString)) { var affrows = conn.Delete() .Where(a => a.Id == xxx) .ExecuteAffrows(); } ``` 新增或更新: ```c# using (var conn = new SqlConnection(connectString)) { var affrows = conn.InsertOrUpdate() .SetSource(item) .ExecuteAffrows(); } ``` 如上新增、刪除、修改、查詢,已經支援實體類操作,並且支援批量插入、批量更新、批量刪除、多表查詢、導航屬性查詢。 可以享用 FreeSql 幾乎所有功能。 思考:使用這種 API 貌似可以很輕鬆的接入到 abp vnext 中? ## 結束語 FreeSql 使用世界上最寬鬆的開源協議 MIT 託管於 github:https://github.com/dotnetcore/FreeSql 目前已釋出經歷兩年高頻率迭代的穩定版本 v2.0,歡迎關注和使用。 支援 .NetFramework 4.0+、.NetCore 2.1+、Xamarin 等支援 NetStandard 所有執行平臺。 支援 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達夢/神通/人大金倉/翰高/MsAccess 資料庫,支援 Ado.net/Odbc。 QQ群:4336577(已滿)、8578575(線上)、52508226(線上) ![](https://img2020.cnblogs.com/blog/31407/202012/31407-20201207092143960-960862465.png)