From 36b28eb7737d3f22459650820ec425ecc5c3cdef Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Fri, 28 Feb 2020 09:32:21 +0800 Subject: [PATCH] update --- FluentApi.md | 22 +++++++++++++++--- 入门.md | 2 +- 分组聚合查询.md | 3 --- 分页查询.md | 4 +--- 单表查询.md | 19 +++++++++------ 多表查询.md | 62 ++++++++++++++++++++++++++++--------------------- 延时加载.md | 2 +- 租户.md | 2 +- 自定义特性.md | 2 ++ 表达式函数.md | 20 ++++++++-------- 读写分离.md | 5 ++-- 骚操作.md | 49 +++++++++----------------------------- 12 files changed, 97 insertions(+), 95 deletions(-) diff --git a/FluentApi.md b/FluentApi.md index 5cf4f9e..ba48a07 100644 --- a/FluentApi.md +++ b/FluentApi.md @@ -1,4 +1,4 @@ - +FreeSql 提供使用 Fluent Api, 在外部配置实体的数据库特性,Fluent Api 的方法命名与特性名保持一致,如下: ```csharp fsql.CodeFirst @@ -12,11 +12,27 @@ fsql.CodeFirst a.Property(b => b.Id).Name("Id22").IsIdentity(true); a.Property(b => b.name).DbType("varchar(100)").IsNullable(true); }); + +//以下为实体类 +class TestFluenttb1 +{ + public int Id { get; set; } + public string name { get; set; } = "defaultValue"; +} + +[Table(Name = "cccccdddwww")] +class TestFluenttb2 +{ + public int Id { get; set; } + public string name { get; set; } = "defaultValue"; +} ``` -最好在程序初始化执行,并且这段配置最好只执行一次,避免性能损耗。 +> fsql 是一个 IFreeSql 对象 -FluentApi 的命名与特性保持一致,有关说明请移步参考:[《实体特性说明》](https://github.com/2881099/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7) +> 这段配置尽量只执行一次,避免性能损耗 + +参考:[《实体特性说明》](https://github.com/2881099/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7) > v1.1 增加扩展包 [FreeSql.Extensions.EfCoreFluentApi](https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.EfCoreFluentApi),方便 EfCore 使用者过渡,使用方法接近 EfCore diff --git a/入门.md b/入门.md index b38f566..d94fd43 100644 --- a/入门.md +++ b/入门.md @@ -1,4 +1,4 @@ -FreeSql 是一个功能强大的对象关系映射程序(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.0+(QQ群:4336577) +FreeSql是一个功能强大的 .NET ORM 功能库,支持 .NetFramework 4.0+、.NetCore 2.1+、Xamarin 等支持 NetStandard 所有运行平台。(QQ群:4336577) ## 模型 diff --git a/分组聚合查询.md b/分组聚合查询.md index d0eb9f5..439ba68 100644 --- a/分组聚合查询.md +++ b/分组聚合查询.md @@ -8,12 +8,9 @@ class Topic { [Column(IsIdentity = true, IsPrimary = true)] public int Id { get; set; } public int Clicks { get; set; } - public int TestTypeInfoGuid { get; set; } public string Title { get; set; } public DateTime CreateTime { get; set; } } - -ISelect select => fsql.Select(); ``` ## 分组聚合 diff --git a/分页查询.md b/分页查询.md index a59c4c9..8967d7f 100644 --- a/分页查询.md +++ b/分页查询.md @@ -12,14 +12,12 @@ class Topic { public string Title { get; set; } public DateTime CreateTime { get; set; } } - -ISelect select => fsql.Select(); ``` ## 每页20条数据,查询第1页 ```csharp -var sql = select.Page(1, 20).ToSql(); +var sql = fsql.Select().Page(1, 20).ToSql(); ///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //LIMIT 0,20 diff --git a/单表查询.md b/单表查询.md index 5ef31d8..351360d 100644 --- a/单表查询.md +++ b/单表查询.md @@ -12,23 +12,27 @@ class Topic { public string Title { get; set; } public DateTime CreateTime { get; set; } } - -ISelect select => fsql.Select(); ``` ## 单表 ```csharp -var sql = select.Where(a => a.Id == 10).ToSql(); +var sql = fsql.Select() + .Where(a => a.Id == 10) + .ToSql(); ///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //WHERE (a.`Id` = 10) -sql = select.Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100).ToSql(); +sql = fsql.Select() + .Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100) + .ToSql(); ///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //WHERE (a.`Id` = 10 AND a.`Id` > 10 OR a.`Clicks` > 100) -sql = select.Where(a => new []{1,2,3}.Contains(a.Id)).ToSql(); +sql = fsql.Select() + .Where(a => new []{1,2,3}.Contains(a.Id)) + .ToSql(); //SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //WHERE (a.`Id` in (1,2,3)) @@ -37,8 +41,9 @@ sql = select.Where(a => new []{1,2,3}.Contains(a.Id)).ToSql(); ## 巧用AsTable ```csharp var sql = fsql.Select() - .AsTable((a, b) => "(select * from user where clicks > 10)") - .Page(1, 10).ToList() + .AsTable((a, b) => "(select * from user where clicks > 10)") + .Page(1, 10) + .ToList() ``` > v1.0.1 ISelect 增加 WithSql("select * from user ...") 功能快速代理此方法 diff --git a/多表查询.md b/多表查询.md index 0ba77f8..d3395c2 100644 --- a/多表查询.md +++ b/多表查询.md @@ -24,15 +24,14 @@ class TestTypeParentInfo { public int Id { get; set; } public string Name { get; set; } } - -ISelect select => fsql.Select(); ``` ## 1、导航属性联表 ```csharp -sql = select - .LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid) - .LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId).ToSql(); +sql = fsql.Select() + .LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid) + .LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId) + .ToSql(); //SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a__Type.`Guid`, a__Type.`ParentId`, a__Type.`Name`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //LEFT JOIN `TestTypeInfo` a__Type ON a__Type.`Guid` = a.`TestTypeInfoGuid` @@ -43,7 +42,9 @@ sql = select ## 2、普通联表 ```csharp -sql = select.LeftJoin((a, b) => b.Guid == a.TestTypeInfoGuid).ToSql(); +sql = fsql.Select() + .LeftJoin((a, b) => b.Guid == a.TestTypeInfoGuid) + .ToSql(); //SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //LEFT JOIN `TestTypeInfo` b ON b.`Guid` = a.`TestTypeInfoGuid` @@ -51,14 +52,16 @@ sql = select.LeftJoin((a, b) => b.Guid == a.TestTypeInfoGuid).ToSq ## 3、复杂联表 ```csharp -sql = select.From((s, b, c) => s - .LeftJoin(a => a.TestTypeInfoGuid == b.Guid) - .LeftJoin(a => b.ParentId == c.Id)).ToSql(); +sql = fsql.Select().From((s, b, c) => s + .LeftJoin(a => a.TestTypeInfoGuid == b.Guid) + .LeftJoin(a => b.ParentId == c.Id)) + .ToSql(); //或者 sql = fsql.Select() - .LeftJoin((a,b,c) => a.TestTypeInfoGuid == b.Guid) - .LeftJoin((a,b,c) => b.ParentId == c.id).ToSql(); + .LeftJoin((a,b,c) => a.TestTypeInfoGuid == b.Guid) + .LeftJoin((a,b,c) => b.ParentId == c.id) + .ToSql(); //SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //LEFT JOIN `TestTypeInfo` b ON a.`TestTypeInfoGuid` = b.`Guid` @@ -67,7 +70,9 @@ sql = fsql.Select() ## 4、SQL联表 ```csharp -sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname", new { bname = "xxx" }).ToSql(); +sql = fsql.Select() + .LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname", new { bname = "xxx" }) + .ToSql(); //SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime` //FROM `tb_topic` a //LEFT JOIN TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname @@ -75,7 +80,9 @@ sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name ## 5、子表Exists ```csharp -var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToList(); +var list2 = fsql.Select() + .Where(a => fsql.Select().As("b").Where(b => b.Id == a.Id).Any()) + .ToList(); // SELECT a.`Id`, a.`TypeGuid`, a.`Title`, a.`CreateTime` // FROM `xxx` a // WHERE (exists(SELECT 1 @@ -88,7 +95,9 @@ var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToL ## 6、子表In ```csharp -var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).ToList(); +var list2 = fsql.Select() + .Where(a => fsql.Select().As("b").ToList(b => b.Id).Contains(a.Id)) + .ToList(); // SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` // FROM `tb_topic` a // WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` @@ -97,14 +106,15 @@ var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).T ## 7、子表First/Count/Sum/Max/Min/Avg ```csharp -var subquery = select.ToSql(a => new { - all = a, - first = fsql.Select().Where(b => b.ParentId == a.Id).First(b => b.Id), - count = fsql.Select().Where(b => b.ParentId == a.Id).Count(), - sum = fsql.Select().Where(b => b.ParentId == a.Id).Sum(b => b.Score), - max = fsql.Select().Where(b => b.ParentId == a.Id).Max(b => b.Score), - min = fsql.Select().Where(b => b.ParentId == a.Id).Min(b => b.Score), - avg = fsql.Select().Where(b => b.ParentId == a.Id).Avg(b => b.Score) +var subquery = fsql.Select().ToSql(a => new +{ + all = a, + first = fsql.Select().Where(b => b.ParentId == a.Id).First(b => b.Id), + count = fsql.Select().Where(b => b.ParentId == a.Id).Count(), + sum = fsql.Select().Where(b => b.ParentId == a.Id).Sum(b => b.Score), + max = fsql.Select().Where(b => b.ParentId == a.Id).Max(b => b.Score), + min = fsql.Select().Where(b => b.ParentId == a.Id).Min(b => b.Score), + avg = fsql.Select().Where(b => b.ParentId == a.Id).Avg(b => b.Score) }); ``` @@ -112,16 +122,16 @@ var subquery = select.ToSql(a => new { ```csharp fsql.Select() - .Where(a => a.Topics.AsSelect().Any(b => b.Title.Contains("xx"))) - .ToSql(); + .Where(a => a.Topics.AsSelect().Any(b => b.Title.Contains("xx"))) + .ToSql(); ``` 效果等同于: ```csharp fsql.Select() - .Where(a => fsql.Select().Any(b => b.Title.Contains("xx"))) - .ToSql(); + .Where(a => fsql.Select().Any(b => b.Title.Contains("xx"))) + .ToSql(); ``` 将集合属性快速转换为 ISelect 进行子查询操作。 diff --git a/延时加载.md b/延时加载.md index 97dcc84..82fb8ad 100644 --- a/延时加载.md +++ b/延时加载.md @@ -27,7 +27,7 @@ public class OrderDetail { > 延时加载功能,依赖 FreeSql.Extensions.LazyLoading 包,请前往 nuget 下载; ```csharp -IFreeSql fsql = new FreeSql.FreeSqlBuilder() +static 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") .UseLazyLoading(true) //开启延时加载功能 .UseMonitorCommand( diff --git a/租户.md b/租户.md index af03745..d2cc9ee 100644 --- a/租户.md +++ b/租户.md @@ -41,7 +41,7 @@ LEFT JOIN t2 on ... AND (t2.IsDeleted = 0) WHERE t1.IsDeleted = 0 ``` -其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 +实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 可应用范围: diff --git a/自定义特性.md b/自定义特性.md index 715af5b..0b83476 100644 --- a/自定义特性.md +++ b/自定义特性.md @@ -22,6 +22,8 @@ class ModelAopConfigEntity { } ``` +> v1.1 增加扩展包 [FreeSql.Extensions.EfCoreFluentApi](https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.EfCoreFluentApi),方便 EfCore 使用者过渡,使用方法接近 EfCore + ## 优先级 数据库特性 > 实体特性 > FluentApi(配置特性) > Aop(配置特性) diff --git a/表达式函数.md b/表达式函数.md index cd6e109..be7673e 100644 --- a/表达式函数.md +++ b/表达式函数.md @@ -83,20 +83,20 @@ var t4 = fsql.Select() [ExpressionCall] public static class DbFunc { - //必要定义 static + ThreadLocal - static ThreadLocal context = new ThreadLocal(); + //必要定义 static + ThreadLocal + static ThreadLocal context = new ThreadLocal(); - public static DateTime FormatDateTime(this DateTime that, string arg1) - { - var up = context.Value; - if (up.DataType == FreeSql.DataType.Sqlite) //重写内容 - context.Value.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})"; - return that; - } + public static DateTime FormatDateTime(this DateTime that, string arg1) + { + var up = context.Value; + if (up.DataType == FreeSql.DataType.Sqlite) //重写内容 + up.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})"; + return that; + } } var sql1 = fsql.Select() - .ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd")); + .ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd")); //SELECT date_format(a."CreateTime", 'yyyy-MM-dd') as1 //FROM "SysModule" a ``` diff --git a/读写分离.md b/读写分离.md index 9338f34..79f7220 100644 --- a/读写分离.md +++ b/读写分离.md @@ -23,8 +23,9 @@ static IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个 .Build(); //请务必定义成 Singleton 单例模式 -select.Where(a => a.Id == 1).ToOne(); //读【从库】(默认) -select.Master().WhereId(a => a.Id == 1).ToOne(); //强制读【主库】 +fsql.Select().Where(a => a.Id == 1).ToOne(); //读【从库】(默认) + +fsql.Select().Master().WhereId(a => a.Id == 1).ToOne(); //强制读【主库】 ``` ## 参考资料 diff --git a/骚操作.md b/骚操作.md index b4921a1..418acd0 100644 --- a/骚操作.md +++ b/骚操作.md @@ -173,7 +173,7 @@ LEFT JOIN t2 on ... AND (t2.IsDeleted = 0) WHERE t1.IsDeleted = 0 ``` -其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 +实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 --- @@ -249,49 +249,22 @@ SaveMany【多对多】的机制规则与联级保存的一样,如下: [ExpressionCall] public static class DbFunc { - //必要定义 static + ThreadLocal - static ThreadLocal context = new ThreadLocal(); + //必要定义 static + ThreadLocal + static ThreadLocal context = new ThreadLocal(); - public static DateTime FormatDateTime(this DateTime that, string arg1) - { - var up = context.Value; - if (up.DataType == FreeSql.DataType.Sqlite) //重写内容 - context.Value.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})"; - return that; - } - - public static string SetDbParameter(this string that, int size) - { - if (context.Value.DbParameter != null) - { - //已经参数化了,直接修改长度 - //提示:此条件可能开启了全局表达式参数化功能 UseGenerateCommandParameterWithLambda(true) - context.Value.DbParameter.Size = size; - return that; - } - var guid = Guid.NewGuid().ToString("N").ToLower(); - context.Value.UserParameters.Add(new SqlParameter - { - ParameterName = guid, - SqlDbType = System.Data.SqlDbType.VarChar, - Size = size, - Value = that - }); - return $"@{guid}"; //重写内容 - } + public static DateTime FormatDateTime(this DateTime that, string arg1) + { + var up = context.Value; + if (up.DataType == FreeSql.DataType.Sqlite) //重写内容 + up.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})"; + return that; + } } var sql1 = fsql.Select() - .ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd")); + .ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd")); //SELECT date_format(a."CreateTime", 'yyyy-MM-dd') as1 //FROM "SysModule" a - -var sql2 = fsql.Select() - .Where(a => a.Title == "123123".SetDbParameter(20)) - .ToSql(); -//SELECT ... -//FROM [SysModule] a -//WHERE (a.[Title] = @6a8b79d7001540369a2f52ecbba15679) ``` \[ExpressionCall\] 特性可在静态扩展类上标记,也可以在单个静态方法上标记;