FreeSql 采用 ExpressionTree 優化讀取速讀,如果懂技術的你一定知道 .NETCore 技術下除了原生代碼,最快就是 Emit 和 ExpressionTree。
項目在初期使用的反射+緩存,雖然 .NETCore 優化了反射性能,但經過與Dapper性能測試對比之后,發現仍然有一定差距,改成 ExpresstionTree 后才與 Dapper 性能相當。
FreeSql 支持的類型較多,實現 ExpressionTree 的復雜度較大,有興趣的朋友可以翻閱源代碼。
IFreeSql fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10").Build();[Table(Name = "tb_topic")]
class Topic {[Column(IsIdentity = true, IsPrimary = true)]public int Id { get; set; }public int Clicks { get; set; }public int TestTypeInfoGuid { get; set; }public TestTypeInfo Type { get; set; }public string Title { get; set; }public DateTime CreateTime { get; set; }
}
class TestTypeInfo {public int Guid { get; set; }public int ParentId { get; set; }public TestTypeParentInfo Parent { get; set; }public string Name { get; set; }
}
class TestTypeParentInfo {public int Id { get; set; }public string Name { get; set; }
}ISelect<Topic> select => fsql.Select<Topic>();
返回單條記錄
Topic t1 = select.Where(a => a.Id == 1).ToOne();
FreeSql有一個約定,ToOne 永遠返回 null 或 有數據的實體對象,ToList 永遠返回非 null 的 List<實體類型>
返回 List
List<Topic> t1 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList();
返回 List + 導航屬性的數據
List<Topic> t2 = select.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid).ToList();
//此時會返回普通字段 + 導航對象 Type 的數據
指定字段返回
//返回一個字段
List<int> t3 = select.Where(a => a.Id > 0).ToList(a => a.Id);//返回匿名類
List<匿名類> t4 = select.Where(a => a.Id > 0).ToList(a => new { a.Id, a.Title });//返回元組
List<(int, string)> t5 = select.Where(a => a.Id > 0).ToList<(int, string)>("id, title");//返回指定映射字段
List<(int, string)> t6 = select.Where(a => a.Id > 0).ToList<Dto>();//返回SQL字段
List<匿名類> t7 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList(a => new {a.Id,a.Title,cstitle = "substr(a.title, 0, 2)", //將 substr(a.title, 0, 2) 作為查詢字段csnow = Convert.ToDateTime("now()"), //將 now() 作為查詢字段//奇思妙想:怎么查詢開窗函數的結果});//返回更為復雜的結構
List<匿名類> t8 = select.From<TestTypeInfo, TestTypeParentInfo>((s, b, c) => s.InnerJoin(a => a.TypeGuid == b.Guid).LeftJoin(a => c.Id == b.ParentId).Where(a => b.Name != "xxx")).ToList((a, b, c) => new {a.Id,a.Title,a.Type,ccc = new { a.Id, a.Title },tp = a.Type,tp2 = new {a.Id,tp2 = a.Type.Name},tp3 = new {a.Id,tp33 = new {a.Id}}});
執行SQL
class xxx {public int Id { get; set; }public string Path { get; set; }public string Title2 { get; set; }
}List<xxx> t9 = fsql.Ado.Query<xxx>("select * from song");
List<(int, string ,string)> t10 = fsql.Ado.Query<(int, string, string)>("select * from song");
List<dynamic> t11 = fsql.Ado.Query<dynamic>("select * from song");
巧用AsTable
var t12 = fsql.Select<User>().AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList()
ToChunk
執行查詢,分塊返回數據,可減少內存開銷。比如讀取10萬條數據,每次返回100條處理。
var testlist1 = fsql.Select<Song>().OrderBy(a => a.Id).ToList();
var testlist2 = new List<Song>();
fsql.Select<Song>().OrderBy(a => a.Id).ToChunk(100, list =>
{testlist2.AddRange(list);
});
//這里示范,最終 testlist1 與 testlist2 返回的數據相同。
API
方法 | 返回值 | 參數 | 描述 |
---|---|---|---|
ToSql | string | 返回即將執行的SQL語句 | |
ToList | List | 執行SQL查詢,返回 T1 實體所有字段的記錄,若存在導航屬性則一起查詢返回,記錄不存在時返回 Count 為 0 的列表 | |
ToList<Dto> | List<Dto> | Lambda | 執行SQL查詢,返回指定字段或Dto映射的記錄,記錄不存在時返回 Count 為 0 的列表 |
ToList<T> | List<T> | string field | 執行SQL查詢,返回 field 指定字段的記錄,并以元組或基礎類型(int,string,long)接收,記錄不存在時返回 Count 為 0 的列表 |
ToOne | T1 | 執行SQL查詢,返回 T1 實體所有字段的第一條記錄,記錄不存在時返回 null | |
ToChunk | <空> | int size, Action<List<T1>> done | 執行SQL查詢,分塊返回數據,可減少內存開銷。比如讀取10萬條數據,每次返回100條處理。 |
Any | bool | 執行SQL查詢,是否有記錄 | |
Sum | T | Lambda | 指定一個列求和 |
Min | T | Lambda | 指定一個列求最小值 |
Max | T | Lambda | 指定一個列求最大值 |
Avg | T | Lambda | 指定一個列求平均值 |
系列文章導航
(一)入門
(二)自動遷移實體
(三)實體特性
(四)實體特性 Fluent Api
(五)插入數據
(六)批量插入數據
(七)插入數據時忽略列
(八)插入數據時指定列
(九)刪除數據
(十)更新數據
(十一)更新數據 Where
(十二)更新數據時指定列
(十三)更新數據時忽略列
(十四)批量更新數據
(十五)查詢數據
(十六)分頁查詢
(十七)聯表查詢
(十八)導航屬性
(十九)多表查詢
(二十)多表查詢 WhereCascade
(二十一)查詢返回數據
(二十二)Dto 映射查詢
(二十三)分組、聚合
(二十四)Linq To Sql 語法使用介紹
(二十五)延時加載
(二十六)貪婪加載 Include、IncludeMany、Dto、ToList
(二十七)將已寫好的 SQL 語句,與實體類映射進行二次查詢
(二十八)事務
(二十九)Lambda 表達式
(三十)讀寫分離
(三十一)分區分表
(三十二)Aop
(三十三)CodeFirst 類型映射
(三十四)CodeFirst 遷移說明
(三十五)CodeFirst 自定義特性