From abd17cec40e26734e04690ef713c4279c3cc8675 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Thu, 27 Feb 2020 17:25:35 +0800 Subject: [PATCH] update --- Repository.md | 7 ++--- 单表查询.md | 2 +- 多表查询.md | 70 +++++++++-------------------------------- 导入数据库特性.md | 2 ++ 表达式函数.md | 80 ++++++----------------------------------------- 读写分离.md | 4 +-- 6 files changed, 31 insertions(+), 134 deletions(-) diff --git a/Repository.md b/Repository.md index 2453ff7..46e60a5 100644 --- a/Repository.md +++ b/Repository.md @@ -7,7 +7,7 @@ FreeSql.Repository 作为扩展,实现了通用仓储层功能。与其他规 ## 定义 ```csharp -var fsql = new FreeSql.FreeSqlBuilder() +static IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Pooling=true;Max Pool Size=10") .UseAutoSyncStructure(true) //自动迁移实体的结构到数据库 .Build(); //请务必定义成 Singleton 单例模式 @@ -24,11 +24,10 @@ public class Song { 1、IFreeSql 的扩展方法; ```csharp -var curd1 = fsql.GetRepository(); -var curd2 = fsql.GetGuidRepository(); +var curd = fsql.GetRepository(); ``` -> 注意:BaseRepository 对象多线程不安全 +> 注意:多线程不安全 2、继承实现; diff --git a/单表查询.md b/单表查询.md index 2322955..a31d1ac 100644 --- a/单表查询.md +++ b/单表查询.md @@ -1,5 +1,5 @@ ```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") .Build(); //请务必定义成 Singleton 单例模式 diff --git a/多表查询.md b/多表查询.md index 63f2de8..58e3742 100644 --- a/多表查询.md +++ b/多表查询.md @@ -1,5 +1,5 @@ ```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") .Build(); //请务必定义成 Singleton 单例模式 @@ -28,13 +28,8 @@ class TestTypeParentInfo { ISelect select => fsql.Select(); ``` -## 1、(联表)利用导航属性 +## 1、导航属性联表 ```csharp -sql = select.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid).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` - sql = select .LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid) .LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId).ToSql(); @@ -54,24 +49,22 @@ sql = select.LeftJoin((a, b) => b.Guid == a.TestTypeInfoGuid).ToSq //LEFT JOIN `TestTypeInfo` b ON b.`Guid` = a.`TestTypeInfoGuid` ``` -## 3、任意联表 +## 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() + .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` //LEFT JOIN `TestTypeParentInfo` c ON b.`ParentId` = c.`Id` ``` -或者 -```csharp -sql = fsql.Select() - .LeftJoin((a,b,c) => a.TestTypeInfoGuid == b.Guid) - .LeftJoin((a,b,c) => b.ParentId == c.id).ToSql(); -``` - ## 4、SQL联表 ```csharp sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname", new { bname = "xxx" }).ToSql(); @@ -80,42 +73,7 @@ sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name //LEFT JOIN TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname ``` -## 5、利用导航属性,查询条件 -```csharp -sql = select.Where(a => a.Type.Name == "typeTitle" && a.Type.Guid == a.TestTypeInfoGuid).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, `TestTypeInfo` a__Type -//WHERE (a__Type.`Name` = 'typeTitle' AND a__Type.`Guid` = a.`TestTypeInfoGuid`) -``` - -## 6、没有导航属性,查询条件 -```csharp -sql = select.Where((a, b) => b.Guid == a.TestTypeInfoGuid && b.Name == "typeTitle").ToSql(); -//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime` -//FROM `tb_topic` a, `TestTypeInfo` b -//WHERE (b.`Guid` = a.`TestTypeInfoGuid` AND b.`Name` = 'typeTitle') -``` - -## 7、任意条件 -```csharp -sql = select.From((s, b, c) => s - .Where(a => a.Id == 10 && c.Name == "xxx") - .Where(a => b.ParentId == 20)).ToSql(); -//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime` -//FROM `tb_topic` a, `TestTypeParentInfo` c, `TestTypeInfo` b -//WHERE (a.`Id` = 10 AND c.`Name` = 'xxx') AND (b.`ParentId` = 20) -``` - -或者 - -```csharp -sql = fsql.Select() - .Where((a, b, c) => a.Id == 10 && c.Name == "xxxx") - .Where((a, b, c) => b.ParentId == 20) - .ToSql(); -``` - -## 8、子表 Exists +## 5、子表Exists ```csharp var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToList(); // SELECT a.`Id`, a.`TypeGuid`, a.`Title`, a.`CreateTime` @@ -127,7 +85,7 @@ var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToL > 提示:由于子查询的实体类与上层相同,使用 As("b") 指明别名,以便区分 -## 9、子表 In +## 6、子表In ```csharp var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).ToList(); @@ -137,7 +95,7 @@ var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).T // FROM `tb_topic` b))) ``` -## 10、子表 First/Count/Sum/Max/Min/Avg +## 7、子表First/Count/Sum/Max/Min/Avg ```csharp var subquery = select.ToSql(a => new { all = a, @@ -150,7 +108,7 @@ var subquery = select.ToSql(a => new { }); ``` -## 11、AsSelect +## 8、AsSelect ```csharp fsql.Select() @@ -168,7 +126,7 @@ fsql.Select() 将集合属性快速转换为 ISelect 进行子查询操作。 -## 12、WhereCascade +## 9、WhereCascade 多表查询时,像isdeleted每个表都给条件,挺麻烦的。WhereCascade使用后生成sql时,所有表都附上这个条件。 @@ -190,7 +148,7 @@ LEFT JOIN t2 on ... AND (t2.IsDeleted = 0) WHERE t1.IsDeleted = 0 ``` -其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 +实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。 可应用范围: diff --git a/导入数据库特性.md b/导入数据库特性.md index 3972c34..26c7f99 100644 --- a/导入数据库特性.md +++ b/导入数据库特性.md @@ -8,6 +8,8 @@ fsql.CodeFirst.IsConfigEntityFromDbFirst = true; 此功能目前可用于 mysql/sqlserver/postgresql/oracle。 +> 开启该功能会增加首次执行时间(耗时情况和表数量有关) + ## 优先级 数据库特性 > 实体特性 > FluentApi(配置特性) > Aop(配置特性) diff --git a/表达式函数.md b/表达式函数.md index bc42ee7..f0f29a6 100644 --- a/表达式函数.md +++ b/表达式函数.md @@ -18,25 +18,23 @@ var t1 = fsql.Select() 现在:where id in (1..500) or id in (501..1000) or id in (1001..1333) -In 只能实现单列查询,多列怎么办? +## In多列查询 ```csharp //元组集合 vae lst = new List<(Guid, DateTime)>(); +lst.Add((Guid.NewGuid(), DateTime.Now)); +lst.Add((Guid.NewGuid(), DateTime.Now)); -lst.Add((Guid.NewGuid(), DateTime.Now)); -lst.Add((Guid.NewGuid(), DateTime.Now)); -lst.Add((Guid.NewGuid(), DateTime.Now)); var t2 = fsql.Select() .Where(a => lst.Contains(a.Id, a.ct1)) .ToSql(); //SELECT .. FROM .. //WHERE (a."Id" = '685ee1f6-bdf6-4719-a291-c709b8a1378f' AND a."ct1" = '2019-12-07 23:55:27' OR -//a."Id" = '5ecd838a-06a0-4c81-be43-1e77633b7404' AND a."ct1" = '2019-12-07 23:55:27' OR -//a."Id" = 'b8b366f3-1c03-4547-9c96-d362dd5cae6a' AND a."ct1" = '2019-12-07 23:55:27') +//a."Id" = '5ecd838a-06a0-4c81-be43-1e77633b7404' AND a."ct1" = '2019-12-07 23:55:27') ``` -## 子表 In +## In子表 ```csharp var list2 = select.Where(a => select.ToList(b => b.Id).Contains(a.Id)).ToList(); @@ -46,7 +44,7 @@ var list2 = select.Where(a => select.ToList(b => b.Id).Contains(a.Id)).ToList(); // FROM `tb_topic` b))) ``` -## 子表 Exists +## Exists子表 ```csharp var list2 = select.Where(a => select.Where(b => b.Id == a.Id).Any()).ToList(); // SELECT a.`Id`, a.`TypeGuid`, a.`Title`, a.`CreateTime` @@ -63,11 +61,12 @@ var t3 = fsql.Select().Where(a => a.CreateTime.Date == DateTime.Today).ToSql( //这行代码说明 FreeSql 表达式解析强大,不是所有 ORM 都支持 var t4 = fsql.Select().Where(a => a.CreateTime.Between(DateTime.Today, DateTime.Today.AddDays(1))).ToSql(); +//正常用法应该是这样 ``` > SqlServer nvarchar/varchar 已兼容表达式解析,分别解析为:N'' 和 '',优化索引执行计划; -## 自定义表达式函数(v0.11.23) +## 自定义解析 ```csharp [ExpressionCall] @@ -83,39 +82,12 @@ public static class DbFunc 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}"; //重写内容 - } } var sql1 = fsql.Select() .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\] 特性可在静态扩展类上标记,也可以在单个静态方法上标记; @@ -130,7 +102,7 @@ var sql2 = fsql.Select() > 当扩展方法返回值为 string 时,其返回值也可以当作 context.Value.Result 功能 -## 命令参数化(v0.12.1) +## 参数化 在之前 Where(lambda) 解析出来的是纯文本,做了防止注入功能,对数据库执行计划要求高的,现在可以开启 lambda 参数化功能。 @@ -184,40 +156,6 @@ public static class DbFunc ![image](https://user-images.githubusercontent.com/16286519/69433211-2c5fcf80-0d76-11ea-8eec-963eb37199c5.png) -## AOP拦截解析 - -IFreeSql 对象有 Aop 成员,那里提供一堆 AOP 拦截的方法。其实有一个事件名称:ParseExpression。 - -```csharp -/// -/// 可自定义解析表达式 -/// -EventHandler ParseExpression { get; set; } - -public class AopParseExpressionEventArgs : EventArgs { - public AopParseExpressionEventArgs(Expression expression, Func freeParse) { - this.Expression = expression; - this.FreeParse = freeParse; - } - - /// - /// 内置解析功能,可辅助您进行解析 - /// - public Func FreeParse { get; } - - /// - /// 需要您解析的表达式 - /// - public Expression Expression { get; } - /// - /// 解析后的内容 - /// - public string Result { get; set; } -} -``` - -FreeParse 是提供给外部的解析工具,它拥有 FreeSql 所有表达式功能,当您自定义解析的过程中遇到特别难处理的,可通过它快速解析出表达式的子部分内容。 - ## 表达式函数全览 | 表达式 | MySql | SqlServer | PostgreSQL | Oracle | 功能说明 | diff --git a/读写分离.md b/读写分离.md index 55b34fa..9338f34 100644 --- a/读写分离.md +++ b/读写分离.md @@ -4,7 +4,7 @@ FreeSql 支持数据库读写分离,本功能是客户端的读写分离行为 1、nginx代理,配置繁琐且容易出错; -2、中件间,如MyCat,MySql可以其他数据库怎么办? +2、中件间,如MyCat; 3、在client端支持; @@ -18,7 +18,7 @@ FreeSql 实现了第3种方案,支持一个【主库】多个【从库】, var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10"; -IFreeSql fsql = new FreeSql.FreeSqlBuilder() +static IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, connstr) .UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个 .Build(); //请务必定义成 Singleton 单例模式