From 7a64f9d65f4bbcfa3a3c60f4e3dc7ba37340ada0 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 29 Dec 2022 16:17:10 +0800 Subject: [PATCH 1/6] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20ClickHouse=20like?= =?UTF-8?q?=20=E4=B8=BA=20positionCaseInsensitive=20#1386?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ClickHouseExpression.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs index aa4c964a..bcab608c 100644 --- a/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs +++ b/Providers/FreeSql.Provider.ClickHouse/ClickHouseExpression.cs @@ -317,16 +317,9 @@ namespace FreeSql.ClickHouse case "Contains": var args0Value = getExp(exp.Arguments[0]); if (args0Value == "NULL") return $"({left}) IS NULL"; - if (args0Value.Contains("%")) - { - if (exp.Method.Name == "StartsWith") return $"locate({args0Value}, {left}) = 1"; - if (exp.Method.Name == "EndsWith") return $"locate({args0Value}, {left}) = char_length({args0Value})"; - return $"locate({args0Value}, {left}) > 0"; - } - if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}"; + if (exp.Method.Name == "StartsWith") return $"positionCaseInsensitive({left}, {args0Value}) = 1"; if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}"; - if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"; - return $"({left}) LIKE concat('%', {args0Value}, '%')"; + return $"positionCaseInsensitive({left}, {args0Value}) > 0"; case "ToLower": return $"lower({left})"; case "ToUpper": return $"upper({left})"; case "Substring": From 1613307f26a9d9a8e5733e4acaecaefafb200c48 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 29 Dec 2022 16:23:21 +0800 Subject: [PATCH 2/6] =?UTF-8?q?-=20=E4=BC=98=E5=8C=96=20JsonMap=20?= =?UTF-8?q?=E5=AF=B9=E5=9F=BA=E7=A1=80=E7=B1=BB=E5=9E=8B=E7=9A=84=E6=97=A0?= =?UTF-8?q?=E6=95=88=E5=88=A4=E6=96=AD=EF=BC=9B#1385?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs b/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs index 25ab7407..12ca516d 100644 --- a/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs +++ b/Extensions/FreeSql.Extensions.JsonMap/JsonMapCore.cs @@ -53,6 +53,9 @@ public static class FreeSqlJsonMapCoreExtensions var isJsonMap = e.Property.GetCustomAttributes(typeof(JsonMapAttribute), false).Any() || _dicJsonMapFluentApi.TryGetValue(e.EntityType, out var tryjmfu) && tryjmfu.ContainsKey(e.Property.Name); if (isJsonMap) { + if (FreeSql.Internal.Utils.dicExecuteArrayRowReadClassOrTuple.ContainsKey(e.Property.PropertyType)) + return; //基础类型使用 JsonMap 无效 + e.ModifyResult.MapType = typeof(string); e.ModifyResult.StringLength = -2; if (_dicTypes.TryAdd(e.Property.PropertyType, true)) From 36f3db55252cbbb3e390a2460f28e69af9babd25 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 29 Dec 2022 16:51:19 +0800 Subject: [PATCH 3/6] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20AsType=20=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98=EF=BC=9B?= =?UTF-8?q?#1389?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 63 +++++++++++++++++++------ FreeSql.DbContext/FreeSql.DbContext.xml | 18 +++++++ FreeSql/Internal/CommonExpression.cs | 7 ++- 3 files changed, 73 insertions(+), 15 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index 0adbd60a..e001da0f 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -443,7 +443,7 @@ namespace base_entity .UseNoneCommandParameter(true) .UseNameConvert(NameConvertType.ToLower) .UseMappingPriority(MappingPriorityType.Attribute, MappingPriorityType.FluentApi, MappingPriorityType.Aop) - + .UseConnectionString(FreeSql.DataType.Sqlite, "data source=:memory:") //.UseConnectionString(DataType.Sqlite, "data source=db1.db;attachs=db2.db") @@ -491,6 +491,17 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + var sqlv01 = fsql.Select().AsType(typeof(GoodsData)) + .ToSql(v => new GoodsDataDTO() + { + Id = v.Id, + GoodsNo = v.Code, + GoodsName = v.Name, + }); + // 解析会连带导出 CategoryId ,但是如果查询别名不是 a 时就会重置到基类表 + // SELECT a.`CategoryId` as1, v.`Id` as2, v.`Code` as3, v.`Name` as4 + // FROM `FreeSqlTest`.`bdd_1` a, `BaseDataEntity` v + var groupsql01 = fsql.Select() .GroupBy(a => new { @@ -524,9 +535,9 @@ namespace base_entity fsql.Insert(listaaaddd).ExecuteAffrows(); //加在事务里就出错 }); - fsql.Select().Count(); + fsql.Select().Count(); - var dkdksql = fsql.Select().WithLock().From() + var dkdksql = fsql.Select().WithLock().From() .InnerJoin((user, usergroup) => user.GroupId == usergroup.Id && usergroup.GroupName == "xxx") .ToSql(); @@ -791,7 +802,7 @@ namespace base_entity .Where(a => a.Id == a1id1 || a.Id == a1id2) .ToSql(); var sql1a2 = fsql.Select() - .InnerJoin((a,b)=> a.GroupId == b.Id) + .InnerJoin((a, b) => a.GroupId == b.Id) .Where((a, b) => a.Id == a1id1) .WithTempQuery((a, b) => new { user = a, group = b }) //匿名类型 @@ -823,8 +834,8 @@ namespace base_entity fsql.CodeFirst.ConfigEntity(cf => { - cf.Property(p => p.Name).IsNullable(false); - cf.Property(p => p.Tags).JsonMap(); + cf.Property(p => p.Name).IsNullable(false); + cf.Property(p => p.Tags).JsonMap(); }); fsql.Insert(new TestClass("test 1") @@ -1029,7 +1040,7 @@ namespace base_entity if (CommandTimeoutCascade._asyncLocalTimeout.Value > 0) e.Command.CommandTimeout = CommandTimeoutCascade._asyncLocalTimeout.Value; }; - + using (new CommandTimeoutCascade(1000)) { fsql.Select().ToList(); @@ -1043,7 +1054,8 @@ namespace base_entity .Where((a, b) => a.IsDeleted == false) .ToSql((a, b) => new { - user = a, group = b + user = a, + group = b }); sql1 = sql1.Replace("INNER JOIN ", "FULL JOIN "); @@ -1100,7 +1112,8 @@ namespace base_entity groups11 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(), groups22 = fsql.Select().Where(c => c.Id == b.GroupId).ToList(c => new { - c.Id, c.GroupName, + c.Id, + c.GroupName, username = b.Username, }) }), @@ -1370,10 +1383,10 @@ namespace base_entity fsql.Aop.AuditValue += new EventHandler((_, e) => { - + }); - + for (var a = 0; a < 10000; a++) @@ -1526,7 +1539,7 @@ namespace base_entity }, ] } -"); +"); var config = new JsonSerializerOptions() { PropertyNamingPolicy = null, @@ -1637,9 +1650,9 @@ namespace base_entity //fsql.Aop.ConfigEntityProperty += ConfigEntityProperty; - - + + Console.WriteLine("按任意键结束。。。"); Console.ReadKey(); @@ -1805,4 +1818,26 @@ namespace base_entity [Column(Name = "更新时间", CanInsert = false, CanUpdate = true, ServerTime = DateTimeKind.Local)] public DateTime 更新时间 { get; set; } } + + abstract class BaseDataEntity + { + public Guid Id { get; set; } + public virtual int CategoryId { get; set; } + public virtual string Code { get; set; } + public virtual string Name { get; set; } + } + [Table(Name = "`FreeSqlTest`.`bdd_1`")] + class GoodsData : BaseDataEntity + { + public override Int32 CategoryId { get; set; } + public override string Code { get; set; } + public override string Name { get; set; } + } + class GoodsDataDTO + { + public Guid Id { get; set; } + public int CategoryId { get; set; } + public string GoodsNo { get; set; } + public string GoodsName { get; set; } + } } diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 594fbad3..26522f10 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -733,6 +733,15 @@ + + + 根据Assembly扫描所有继承IEntityTypeConfiguration<T>的配置类 + + + + + + 创建普通数据上下文档对象 @@ -791,5 +800,14 @@ + + + 批量注入 Repository,可以参考代码自行调整 + + + + + + diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 85867997..ae0b7ea5 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1715,7 +1715,12 @@ namespace FreeSql.Internal if (oper2.NodeType == ExpressionType.Parameter) { var oper2Parm = oper2 as ParameterExpression; - expStack.Push(exp2.Type.IsAbstract || exp2.Type.IsInterface || exp2.Type.IsAssignableFrom(oper2Parm.Type) ? oper2Parm : Expression.Parameter(exp2.Type, oper2Parm.Name)); + if (exp2.Type.IsAbstract || exp2.Type.IsInterface || exp2.Type.IsAssignableFrom(oper2Parm.Type)) + expStack.Push(oper2Parm); + else if (oper2Parm.Type.IsAssignableFrom(exp2.Type)) + expStack.Push(oper2Parm); + else + expStack.Push(Expression.Parameter(exp2.Type, oper2Parm.Name)); } else expStack.Push(oper2); From f53863c982cf11e67a79a928b6716ccfa51cc347 Mon Sep 17 00:00:00 2001 From: IGeekFan Date: Thu, 29 Dec 2022 17:21:13 +0800 Subject: [PATCH 4/6] Update docfx.yml --- .github/workflows/docfx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docfx.yml b/.github/workflows/docfx.yml index 9c847436..7410d98b 100644 --- a/.github/workflows/docfx.yml +++ b/.github/workflows/docfx.yml @@ -14,7 +14,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.x + dotnet-version: 7.0.x - name: Remove Examples run: dotnet sln FreeSql.sln remove (ls -r Examples/**/*.csproj) - name: Remove FreeSql.Tests From c8ecadff29034c6d8268925d9a695cc31216d807 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Thu, 29 Dec 2022 17:28:19 +0800 Subject: [PATCH 5/6] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20AsType=20=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E8=A1=A8=E8=BE=BE=E5=BC=8F=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=EF=BC=9B#1389?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FreeSql/Internal/CommonExpression.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index ae0b7ea5..88b07fff 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -1717,7 +1717,7 @@ namespace FreeSql.Internal var oper2Parm = oper2 as ParameterExpression; if (exp2.Type.IsAbstract || exp2.Type.IsInterface || exp2.Type.IsAssignableFrom(oper2Parm.Type)) expStack.Push(oper2Parm); - else if (oper2Parm.Type.IsAssignableFrom(exp2.Type)) + else if (oper2Parm.Type != typeof(object) && oper2Parm.Type.IsAssignableFrom(exp2.Type)) expStack.Push(oper2Parm); else expStack.Push(Expression.Parameter(exp2.Type, oper2Parm.Name)); From 4cd57a0afaf09986c90f3b258f896cf92ee7eadb Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Fri, 30 Dec 2022 11:31:54 +0800 Subject: [PATCH 6/6] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20HzyTuple=20?= =?UTF-8?q?=E5=B5=8C=E5=A5=97=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98=EF=BC=9B?= =?UTF-8?q?#1390?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PostgreSQL/Curd/PostgreSQLInsertTest.cs | 16 +-- .../Curd/SqlServerSelectWithTempQueryTest.cs | 121 +++++++++++++++++- FreeSql/Internal/CommonExpression.cs | 4 + 3 files changed, 128 insertions(+), 13 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs index 6704714b..582c062a 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLInsertTest.cs @@ -54,16 +54,16 @@ namespace FreeSql.Tests.PostgreSQL for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); var sql = insert.AppendData(items.First()).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\", \"title\", \"createtime\") VALUES(@Clicks_0, @Title_0, @CreateTime_0)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\", \"title\", \"createtime\") VALUES(@Clicks_0, @Title_0, @CreateTime_0)", sql); sql = insert.AppendData(items).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\", \"title\", \"createtime\") VALUES(@Clicks_0, @Title_0, @CreateTime_0), (@Clicks_1, @Title_1, @CreateTime_1), (@Clicks_2, @Title_2, @CreateTime_2), (@Clicks_3, @Title_3, @CreateTime_3), (@Clicks_4, @Title_4, @CreateTime_4), (@Clicks_5, @Title_5, @CreateTime_5), (@Clicks_6, @Title_6, @CreateTime_6), (@Clicks_7, @Title_7, @CreateTime_7), (@Clicks_8, @Title_8, @CreateTime_8), (@Clicks_9, @Title_9, @CreateTime_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\", \"title\", \"createtime\") VALUES(@Clicks_0, @Title_0, @CreateTime_0), (@Clicks_1, @Title_1, @CreateTime_1), (@Clicks_2, @Title_2, @CreateTime_2), (@Clicks_3, @Title_3, @CreateTime_3), (@Clicks_4, @Title_4, @CreateTime_4), (@Clicks_5, @Title_5, @CreateTime_5), (@Clicks_6, @Title_6, @CreateTime_6), (@Clicks_7, @Title_7, @CreateTime_7), (@Clicks_8, @Title_8, @CreateTime_8), (@Clicks_9, @Title_9, @CreateTime_9)", sql); sql = insert.AppendData(items).InsertColumns(a => a.Title).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"title\") VALUES(@Title_0), (@Title_1), (@Title_2), (@Title_3), (@Title_4), (@Title_5), (@Title_6), (@Title_7), (@Title_8), (@Title_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"title\") VALUES(@Title_0), (@Title_1), (@Title_2), (@Title_3), (@Title_4), (@Title_5), (@Title_6), (@Title_7), (@Title_8), (@Title_9)", sql); sql = insert.AppendData(items).IgnoreColumns(a => a.CreateTime).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); } [Fact] @@ -73,10 +73,10 @@ namespace FreeSql.Tests.PostgreSQL for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); var sql = insert.AppendData(items).InsertColumns(a => a.Title).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"title\") VALUES(@Title_0), (@Title_1), (@Title_2), (@Title_3), (@Title_4), (@Title_5), (@Title_6), (@Title_7), (@Title_8), (@Title_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"title\") VALUES(@Title_0), (@Title_1), (@Title_2), (@Title_3), (@Title_4), (@Title_5), (@Title_6), (@Title_7), (@Title_8), (@Title_9)", sql); sql = insert.AppendData(items).InsertColumns(a => new { a.Title, a.Clicks }).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); } [Fact] public void IgnoreColumns() @@ -85,10 +85,10 @@ namespace FreeSql.Tests.PostgreSQL for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); var sql = insert.AppendData(items).IgnoreColumns(a => a.CreateTime).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\", \"title\") VALUES(@Clicks_0, @Title_0), (@Clicks_1, @Title_1), (@Clicks_2, @Title_2), (@Clicks_3, @Title_3), (@Clicks_4, @Title_4), (@Clicks_5, @Title_5), (@Clicks_6, @Title_6), (@Clicks_7, @Title_7), (@Clicks_8, @Title_8), (@Clicks_9, @Title_9)", sql); sql = insert.AppendData(items).IgnoreColumns(a => new { a.Title, a.CreateTime }).ToSql(); - Assert.Equal("INSERT INTO \"tb_topic_insert\"(\"clicks\") VALUES(@Clicks_0), (@Clicks_1), (@Clicks_2), (@Clicks_3), (@Clicks_4), (@Clicks_5), (@Clicks_6), (@Clicks_7), (@Clicks_8), (@Clicks_9)", sql); + Assert.Equal("INSERT INTO \"tb_topic_insert2\"(\"clicks\") VALUES(@Clicks_0), (@Clicks_1), (@Clicks_2), (@Clicks_3), (@Clicks_4), (@Clicks_5), (@Clicks_6), (@Clicks_7), (@Clicks_8), (@Clicks_9)", sql); g.pgsql.Delete().Where("1=1").ExecuteAffrows(); var itemsIgnore = new List(); diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs index b878bb02..860bdb3e 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs @@ -40,7 +40,7 @@ FROM ( WHERE (ti2.[RefHeadId] = htb.[HeadId] AND ti2.[RefItemId] = htb.[Id])), 0) [RefQuantity] FROM [bhe_1] a INNER JOIN ( - SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] + SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[RefItemComId] FROM [bie_1] bi WHERE (bi.[IsDeleted] = 0)) htb ON a.[Id] = htb.[HeadId] WHERE (a.[IsDeleted] = 0) ) a @@ -74,7 +74,7 @@ WHERE (((a.[Id]) in (SELECT DISTINCT v.[Id] WHERE (ti2.[RefHeadId] = ht2.[HeadId] AND ti2.[RefItemId] = ht2.[Id])), 0) [RefQuantity] FROM [bhe_1] bh INNER JOIN ( - SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] + SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[RefItemComId] FROM [bie_1] bi WHERE (bi.[IsDeleted] = 0)) ht2 ON bh.[Id] = ht2.[HeadId] WHERE (bh.[IsDeleted] = 0) ) v @@ -111,7 +111,7 @@ RIGHT JOIN ( WHERE (ti2.[RefHeadId] = htb.[HeadId] AND ti2.[RefItemId] = htb.[Id])), 0) [RefQuantity] FROM [bhe_1] a INNER JOIN ( - SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] + SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[RefItemComId] FROM [bie_1] bi WHERE (bi.[IsDeleted] = 0)) htb ON a.[Id] = htb.[HeadId] WHERE (a.[IsDeleted] = 0) ) a @@ -302,7 +302,7 @@ ORDER BY a.[Date] DESC", sql3); .Where(ti => ti.RefHeadId == bi.HeadId && ti.RefItemId == bi.Id) .Sum(ti => ti.Quantity) <= bi.Quantity) .ToSql(); - Assert.Equal(@"SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] + Assert.Equal(@"SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[RefItemComId] FROM [bie_1] bi WHERE (bi.[HeadId] = '62f83a6d-eb53-0608-0097-d177142cadcb' AND bi.[IsDeleted] = 0) AND (isnull((SELECT sum(ti.[Quantity]) FROM [bie_2] ti @@ -324,7 +324,7 @@ WHERE (bi.[HeadId] = '62f83a6d-eb53-0608-0097-d177142cadcb' AND bi.[IsDeleted] = .ToSql(); Assert.Equal(@"SELECT * FROM ( - SELECT bi.[Id], bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[Quantity], isnull((SELECT sum(ti.[Quantity]) + SELECT bi.[Id], bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId], bi.[RefItemComId], bi.[Quantity], isnull((SELECT sum(ti.[Quantity]) FROM [bie_2] ti WHERE (ti.[RefHeadId] = bi.[HeadId] AND ti.[RefItemId] = bi.[Id])), 0) [RefQuantity] FROM [bie_1] bi @@ -375,6 +375,7 @@ WHERE (a.[RefQuantity] < a.[Quantity])", sql2); public decimal Quantity { get; set; } public Guid? RefHeadId { get; set; } public Guid? RefItemId { get; set; } + public Guid? RefItemComId { get; set; } } [Table(Name = "bie_1")] class BiEntity1 : BaseItemEntity { } @@ -382,6 +383,116 @@ WHERE (a.[RefQuantity] < a.[Quantity])", sql2); class BiEntity2 : BaseItemEntity { } #endregion + #region 2022/12/30 + abstract class BaseItemComEntity : SoftDelete + { + public Guid Id { get; set; } + public Guid HeadId { get; set; } + public Guid ItemId { get; set; } + public int GoodsId { get; set; } + public int ComponentId { get; set; } + public decimal Quantity { get; set; } + public int Level { get; set; } + } + [Table(Name = "bic_1")] + class BicEntity1 : BaseItemComEntity { } + [Fact] + public void VicDemo20221230() + { + var fsql = g.mysql; + // 逻辑相同 sql1 能够生成 sql2 就会报类型转换错误 + var sql1 = fsql.Select().AsType(typeof(BicEntity1)).As("bic") + .Where(bic => bic.Level == 0) + .FromQuery(fsql.Select().AsType(typeof(BiEntity1)).As("bi")) + .InnerJoin((bic, bi) => bic.ItemId == bi.Id) + .Where((bic, bi) => bi.IsDeleted == false) + .WithTempQuery((bic, _) => bic) + .FromQuery(fsql.Select().AsType(typeof(BhEntity1)).As("bh")) + .InnerJoin((bic, bh) => bic.HeadId == bh.Id) + .Where((bic, bh) => bh.IsDeleted == false) + .WithTempQuery((bic, _) => new + { + BillItemCom = bic, + RefQuantity = fsql.Select().AsType(typeof(BiEntity1)).As("ti") + .Where(ti => ti.RefHeadId == bic.HeadId) + .Where(ti => ti.RefItemId == bic.ItemId) + .Where(ti => ti.RefItemComId == bic.Id) + .Where(ti => ti.IsDeleted == false) + .FromQuery(fsql.Select().AsType(typeof(BiEntity1))) + .InnerJoin(ti => ti.t1.HeadId == ti.t2.Id) + .Where(ti => ti.t2.IsDeleted == false) + .Sum(ti => ti.t1.Quantity), + }) + .Where(v => v.RefQuantity < v.BillItemCom.Quantity) + .ToSql(); + Assert.Equal(@"SELECT * +FROM ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`ItemId`, a.`GoodsId`, a.`ComponentId`, a.`Quantity`, a.`Level`, ifnull((SELECT sum(ti.`Quantity`) + FROM `bie_1` ti + INNER JOIN ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`GoodsId`, a.`Quantity`, a.`RefHeadId`, a.`RefItemId`, a.`RefItemComId` + FROM `bie_1` a) ht2 ON ti.`HeadId` = ht2.`Id` + WHERE (ti.`RefHeadId` = a.`HeadId`) AND (ti.`RefItemId` = a.`ItemId`) AND (ti.`RefItemComId` = a.`Id`) AND (ti.`IsDeleted` = 0) AND (ht2.`IsDeleted` = 0)), 0) `RefQuantity` + FROM ( + SELECT bic.`IsDeleted`, bic.`Id`, bic.`HeadId`, bic.`ItemId`, bic.`GoodsId`, bic.`ComponentId`, bic.`Quantity`, bic.`Level` + FROM `bic_1` bic + INNER JOIN ( + SELECT bi.`IsDeleted`, bi.`Id`, bi.`HeadId`, bi.`GoodsId`, bi.`Quantity`, bi.`RefHeadId`, bi.`RefItemId`, bi.`RefItemComId` + FROM `bie_1` bi) bi ON bic.`ItemId` = bi.`Id` + WHERE (bic.`Level` = 0) AND (bi.`IsDeleted` = 0) ) a + INNER JOIN ( + SELECT bh.`IsDeleted`, bh.`Id`, bh.`No`, bh.`Date` + FROM `bhe_1` bh) bh ON a.`HeadId` = bh.`Id` + WHERE (bh.`IsDeleted` = 0) ) a +WHERE (a.`RefQuantity` < a.`Quantity`)", sql1); + + var sql2 = fsql.Select().AsType(typeof(BicEntity1)) + .Where(v => v.Level == 0) + .FromQuery(fsql.Select().AsType(typeof(BiEntity1))) + .InnerJoin(v => v.t1.ItemId == v.t2.Id) + .Where(v => v.t2.IsDeleted == false) + .WithTempQuery(v => v.t1) + .FromQuery(fsql.Select().AsType(typeof(BhEntity1))) + .InnerJoin(v => v.t1.HeadId == v.t2.Id) + .Where(v => v.t2.IsDeleted == false) + .WithTempQuery(v => new + { + BillItemCom = v.t1, + RefQuantity = fsql.Select().AsType(typeof(BiEntity1)).As("ti") + .Where(ti => ti.RefHeadId == v.t1.HeadId) + .Where(ti => ti.RefItemId == v.t1.ItemId) + .Where(ti => ti.RefItemComId == v.t1.Id) + .Where(ti => ti.IsDeleted == false) + .FromQuery(fsql.Select().AsType(typeof(BiEntity1))) + .InnerJoin(ti => ti.t1.HeadId == ti.t2.Id) + .Where(ti => ti.t2.IsDeleted == false) + .Sum(ti => ti.t1.Quantity), + }) + .Where(v => v.RefQuantity < v.BillItemCom.Quantity) + .ToSql(); + Assert.Equal(@"SELECT * +FROM ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`ItemId`, a.`GoodsId`, a.`ComponentId`, a.`Quantity`, a.`Level`, ifnull((SELECT sum(ti.`Quantity`) + FROM `bie_1` ti + INNER JOIN ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`GoodsId`, a.`Quantity`, a.`RefHeadId`, a.`RefItemId`, a.`RefItemComId` + FROM `bie_1` a) ht2 ON ti.`HeadId` = ht2.`Id` + WHERE (ti.`RefHeadId` = a.`HeadId`) AND (ti.`RefItemId` = a.`ItemId`) AND (ti.`RefItemComId` = a.`Id`) AND (ti.`IsDeleted` = 0) AND (ht2.`IsDeleted` = 0)), 0) `RefQuantity` + FROM ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`ItemId`, a.`GoodsId`, a.`ComponentId`, a.`Quantity`, a.`Level` + FROM `bic_1` a + INNER JOIN ( + SELECT a.`IsDeleted`, a.`Id`, a.`HeadId`, a.`GoodsId`, a.`Quantity`, a.`RefHeadId`, a.`RefItemId`, a.`RefItemComId` + FROM `bie_1` a) htb ON a.`ItemId` = htb.`Id` + WHERE (a.`Level` = 0) AND (htb.`IsDeleted` = 0) ) a + INNER JOIN ( + SELECT a.`IsDeleted`, a.`Id`, a.`No`, a.`Date` + FROM `bhe_1` a) htb ON a.`HeadId` = htb.`Id` + WHERE (htb.`IsDeleted` = 0) ) a +WHERE (a.`RefQuantity` < a.`Quantity`)", sql2); + } + #endregion + [Fact] public void SingleTablePartitionBy() { diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 88b07fff..efb496d7 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -2320,12 +2320,14 @@ namespace FreeSql.Internal { private List tables; private ParameterExpression[] parameters; + private ParameterExpression lambdaHzyParameter; public LambdaExpression Modify(LambdaExpression lambda, List tables) { this.tables = tables.Where(a => a.Type != SelectTableInfoType.Parent).ToList(); parameters = this.tables.Select(a => a.Parameter ?? Expression.Parameter(a.Table.Type, a.Alias.StartsWith("SP10") ? a.Alias.Replace("SP10", "ht") : a.Alias)).ToArray(); + lambdaHzyParameter = lambda.Parameters.FirstOrDefault(); var exp = Visit(lambda.Body); return Expression.Lambda(exp, parameters); } @@ -2338,6 +2340,7 @@ namespace FreeSql.Internal var parent = node.Expression as MemberExpression; if (parent.Expression?.NodeType == ExpressionType.Parameter && parent.Expression.Type.Name.StartsWith("HzyTuple`") == true && + parent.Expression == lambdaHzyParameter && int.TryParse(parent.Member.Name.Replace("t", ""), out widx) && widx > 0 && widx <= tables.Count) { if (parameters[widx - 1].Type != parent.Type) //解决 BaseEntity + AsTable 时报错 @@ -2348,6 +2351,7 @@ namespace FreeSql.Internal if (node.Expression?.NodeType == ExpressionType.Parameter && node.Expression.Type.Name.StartsWith("HzyTuple`") == true && + node.Expression == lambdaHzyParameter && int.TryParse(node.Member.Name.Replace("t", ""), out widx) && widx > 0 && widx <= tables.Count) { if (parameters[widx - 1].Type != node.Type) //解决 BaseEntity + AsTable 时报错