FreeSql 採用 ExpressionTree 優化讀取速讀,若是懂技術的你必定知道 .NETCore 技術下除了原生代碼,最快就是 Emit 和 ExpressionTree。html
項目在初期使用的反射+緩存,雖然 .NETCore 優化了反射性能,但通過與Dapper性能測試對比以後,發現仍然有必定差距,改爲 ExpresstionTree 後才與 Dapper 性能至關。sql
FreeSql 支持的類型較多,實現 ExpressionTree 的複雜度較大,有興趣的朋友能夠翻閱源代碼。api
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<Topic> t1 = select.Where(a => a.Id > 0).Skip(100).Limit(200).ToList();
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 } } });
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");
var t12 = fsql.Select<User>() .AsTable((a, b) => "(select * from tb_topic where clicks > 10)") .Page(1, 10).ToList()
執行查詢,分塊返回數據,可減小內存開銷。好比讀取10萬條數據,每次返回100條處理。app
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 返回的數據相同。
方法 | 返回值 | 參數 | 描述 |
---|---|---|---|
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 | 指定一個列求平均值 |