mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 01:05:27 +08:00 
			
		
		
		
	- 优化 子查询的多表使用体验;
This commit is contained in:
		@@ -800,5 +800,14 @@
 | 
				
			|||||||
            <param name="that"></param>
 | 
					            <param name="that"></param>
 | 
				
			||||||
            <returns></returns>
 | 
					            <returns></returns>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            批量注入 Repository,可以参考代码自行调整
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="services"></param>
 | 
				
			||||||
 | 
					            <param name="globalDataFilter"></param>
 | 
				
			||||||
 | 
					            <param name="assemblies"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
    </members>
 | 
					    </members>
 | 
				
			||||||
</doc>
 | 
					</doc>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -342,5 +342,13 @@ namespace FreeSql.Tests.ClickHouse
 | 
				
			|||||||
            item = fsql.Select<Entity>().Where(a => a.Id == data2[1].Id).First();
 | 
					            item = fsql.Select<Entity>().Where(a => a.Id == data2[1].Id).First();
 | 
				
			||||||
            Assert.Equal(item.Content, json);
 | 
					            Assert.Equal(item.Content, json);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void DbFirst()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var fsql = g.clickHouse;
 | 
				
			||||||
 | 
					            var tbs = fsql.DbFirst.GetTablesByDatabase();
 | 
				
			||||||
 | 
					            var tbs2 = fsql.DbFirst.GetTablesByDatabase("default");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -9,6 +9,78 @@ namespace FreeSql.Tests.SqlServer
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        #region issues #1215
 | 
					        #region issues #1215
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void VicDemo20220815()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var fsql = g.sqlserver;
 | 
				
			||||||
 | 
					            var subquery1 = fsql.Select<BaseHeadEntity>().AsType(typeof(BhEntity1)).Where(bh => bh.IsDeleted == false)
 | 
				
			||||||
 | 
					                    .FromQuery(fsql.Select<BaseItemEntity>().AsType(typeof(BiEntity1)).As("bi").Where(bi => bi.IsDeleted == false))
 | 
				
			||||||
 | 
					                    .InnerJoin(v => v.t1.Id == v.t2.HeadId)
 | 
				
			||||||
 | 
					                    .WithTempQuery(v => new
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        BillHead = v.t1,
 | 
				
			||||||
 | 
					                        Quantity = v.t2.Quantity,
 | 
				
			||||||
 | 
					                        RefQuantity = fsql.Select<BaseItemEntity>().AsType(typeof(BiEntity2)).As("bi2")
 | 
				
			||||||
 | 
					                            .Where(ti2 => ti2.RefHeadId == v.t2.HeadId && ti2.RefItemId == v.t2.Id)
 | 
				
			||||||
 | 
					                            .Sum(ti2 => ti2.Quantity),
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .Where(v => v.RefQuantity < v.Quantity)
 | 
				
			||||||
 | 
					                    .GroupBy(v => v.BillHead.Id)
 | 
				
			||||||
 | 
					                    .ToSql(v => v.Key);
 | 
				
			||||||
 | 
					            var sql1 = fsql.Select<BaseHeadEntity>().AsType(typeof(BhEntity1))
 | 
				
			||||||
 | 
					                .Where($"a.Id IN ({subquery1})").OrderByDescending(vh => vh.Date)
 | 
				
			||||||
 | 
					                .ToSql();
 | 
				
			||||||
 | 
					            Assert.Equal(@"SELECT a.[IsDeleted], a.[Id], a.[No], a.[Date] 
 | 
				
			||||||
 | 
					FROM [bhe_1] a 
 | 
				
			||||||
 | 
					WHERE (a.Id IN (SELECT a.[Id] as1 
 | 
				
			||||||
 | 
					FROM ( 
 | 
				
			||||||
 | 
					    SELECT a.[IsDeleted], a.[Id], a.[No], a.[Date], SP10b.[Quantity], isnull((SELECT sum(ti2.[Quantity]) 
 | 
				
			||||||
 | 
					        FROM [bie_2] ti2 
 | 
				
			||||||
 | 
					        WHERE (ti2.[RefHeadId] = SP10b.[HeadId] AND ti2.[RefItemId] = SP10b.[Id])), 0) [RefQuantity] 
 | 
				
			||||||
 | 
					    FROM [bhe_1] a 
 | 
				
			||||||
 | 
					    INNER JOIN ( 
 | 
				
			||||||
 | 
					        SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] 
 | 
				
			||||||
 | 
					        FROM [bie_1] bi 
 | 
				
			||||||
 | 
					        WHERE (bi.[IsDeleted] = 0)) SP10b ON a.[Id] = SP10b.[HeadId] 
 | 
				
			||||||
 | 
					    WHERE (a.[IsDeleted] = 0) ) a 
 | 
				
			||||||
 | 
					WHERE (a.[RefQuantity] < a.[Quantity]) 
 | 
				
			||||||
 | 
					GROUP BY a.[Id])) 
 | 
				
			||||||
 | 
					ORDER BY a.[Date] DESC", sql1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var sql2 = fsql.Select<BaseHeadEntity>().AsType(typeof(BhEntity1))
 | 
				
			||||||
 | 
					                .Where(vh => fsql.Select<BaseHeadEntity>().AsType(typeof(BhEntity1)).Where(bh => bh.IsDeleted == false)
 | 
				
			||||||
 | 
					                    .FromQuery(fsql.Select<BaseItemEntity>().AsType(typeof(BiEntity1)).As("bi").Where(bi => bi.IsDeleted == false))
 | 
				
			||||||
 | 
					                    .InnerJoin(v => v.t1.Id == v.t2.HeadId)
 | 
				
			||||||
 | 
					                    .WithTempQuery(v => new
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        BillHead = v.t1,
 | 
				
			||||||
 | 
					                        Quantity = v.t2.Quantity,
 | 
				
			||||||
 | 
					                        RefQuantity = fsql.Select<BaseItemEntity>().AsType(typeof(BiEntity2)).As("bi2")
 | 
				
			||||||
 | 
					                            .Where(ti2 => ti2.RefHeadId == v.t2.HeadId && ti2.RefItemId == v.t2.Id)
 | 
				
			||||||
 | 
					                            .Sum(ti2 => ti2.Quantity),
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .Where(v => v.RefQuantity < v.Quantity)
 | 
				
			||||||
 | 
					                    .Distinct()
 | 
				
			||||||
 | 
					                    .ToList(v => v.BillHead.Id).Contains(vh.Id)
 | 
				
			||||||
 | 
					                ).OrderByDescending(vh => vh.Date)
 | 
				
			||||||
 | 
					                .ToSql();
 | 
				
			||||||
 | 
					            Assert.Equal(@"SELECT a.[IsDeleted], a.[Id], a.[No], a.[Date] 
 | 
				
			||||||
 | 
					FROM [bhe_1] a 
 | 
				
			||||||
 | 
					WHERE (((a.[Id]) in (SELECT DISTINCT v.[Id] 
 | 
				
			||||||
 | 
					    FROM ( 
 | 
				
			||||||
 | 
					        SELECT ht1.[IsDeleted], ht1.[Id], ht1.[No], ht1.[Date], ht2.[Quantity], isnull((SELECT sum(ti2.[Quantity]) 
 | 
				
			||||||
 | 
					            FROM [bie_2] ti2 
 | 
				
			||||||
 | 
					            WHERE (ti2.[RefHeadId] = ht2.[HeadId] AND ti2.[RefItemId] = ht2.[Id])), 0) [RefQuantity] 
 | 
				
			||||||
 | 
					        FROM [BaseHeadEntity] ht1 
 | 
				
			||||||
 | 
					        INNER JOIN ( 
 | 
				
			||||||
 | 
					            SELECT bi.[IsDeleted], bi.[Id], bi.[HeadId], bi.[GoodsId], bi.[Quantity], bi.[RefHeadId], bi.[RefItemId] 
 | 
				
			||||||
 | 
					            FROM [bie_1] bi 
 | 
				
			||||||
 | 
					            WHERE (bi.[IsDeleted] = 0)) ht2 ON ht1.[Id] = ht2.[HeadId] 
 | 
				
			||||||
 | 
					        WHERE (bh.[IsDeleted] = 0) ) v 
 | 
				
			||||||
 | 
					    WHERE (v.[RefQuantity] < v.[Quantity])))) 
 | 
				
			||||||
 | 
					ORDER BY a.[Date] DESC", sql2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void VicDemo20220813()
 | 
					        public void VicDemo20220813()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ public class g
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    static Lazy<IFreeSql> clickHouseLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
 | 
					    static Lazy<IFreeSql> clickHouseLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
 | 
				
			||||||
        .UseConnectionString(FreeSql.DataType.ClickHouse, "Compress=False;BufferSize=32768;SocketTimeout=10000;CheckCompressedHash=False;Encrypt=False;Compressor=lz4;Host=192.168.0.121;Port=8125;Database=PersonnelLocation;Username=root;Password=+riQ8V9D")
 | 
					        .UseConnectionString(FreeSql.DataType.ClickHouse, "Compress=False;BufferSize=32768;SocketTimeout=10000;CheckCompressedHash=False;Encrypt=False;Compressor=lz4;Host=192.168.0.121;Port=8125;Database=PersonnelLocation;Username=root;Password=+riQ8V9D")
 | 
				
			||||||
 | 
					        .UseConnectionString(FreeSql.DataType.ClickHouse, "Compress=False;BufferSize=32768;SocketTimeout=10000;CheckCompressedHash=False;Encrypt=False;Compressor=lz4;Host=139.9.189.145;Port=1386;Database=default;Username=default;Password=Z2C2B4wR")
 | 
				
			||||||
        //.UseAutoSyncStructure(true)
 | 
					        //.UseAutoSyncStructure(true)
 | 
				
			||||||
        //.UseGenerateCommandParameterWithLambda(true)
 | 
					        //.UseGenerateCommandParameterWithLambda(true)
 | 
				
			||||||
        .UseMonitorCommand(
 | 
					        .UseMonitorCommand(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1083,6 +1083,13 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                            case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
					                            case "Min": return $"min({ExpressionLambdaToSql(exp3.Arguments[0], tsc)})";
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (callType.FullName.StartsWith("FreeSql.ISelectGrouping`"))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        switch (exp3.Method.Name)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            case "ToList": return "";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    if (callType.FullName.StartsWith("FreeSql.ISelect`"))
 | 
					                    if (callType.FullName.StartsWith("FreeSql.ISelect`"))
 | 
				
			||||||
                    { //子表查询
 | 
					                    { //子表查询
 | 
				
			||||||
                        switch (exp3.Method.Name)
 | 
					                        switch (exp3.Method.Name)
 | 
				
			||||||
@@ -1310,7 +1317,22 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                                                if (_subSelectParentDiyMemExps.Value == null) _subSelectParentDiyMemExps.Value = new List<BaseDiyMemberExpression>();
 | 
					                                                if (_subSelectParentDiyMemExps.Value == null) _subSelectParentDiyMemExps.Value = new List<BaseDiyMemberExpression>();
 | 
				
			||||||
                                                _subSelectParentDiyMemExps.Value.Add(tsc.diymemexp);
 | 
					                                                _subSelectParentDiyMemExps.Value.Add(tsc.diymemexp);
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
 | 
					                                            switch (method.Name)
 | 
				
			||||||
 | 
					                                            {
 | 
				
			||||||
 | 
					                                                case nameof(ISelect<object>.From):
 | 
				
			||||||
 | 
					                                                case nameof(ISelect<object>.FromQuery):
 | 
				
			||||||
 | 
					                                                case nameof(ISelect<object>.WithTempQuery):
 | 
				
			||||||
 | 
					                                                    fsql = method.Invoke(fsql, args);
 | 
				
			||||||
 | 
					                                                    fsqlType = fsql.GetType();
 | 
				
			||||||
 | 
					                                                    fsqlSelect0 = fsql as Select0Provider; 
 | 
				
			||||||
 | 
					                                                    if (tsc.dbParams != null) fsqlSelect0._params = tsc.dbParams;
 | 
				
			||||||
 | 
					                                                    fsqltables = fsqlSelect0._tables;
 | 
				
			||||||
 | 
					                                                    fsqltable1SetAlias = false;
 | 
				
			||||||
 | 
					                                                    break;
 | 
				
			||||||
 | 
					                                                default:
 | 
				
			||||||
                                                    method.Invoke(fsql, args);
 | 
					                                                    method.Invoke(fsql, args);
 | 
				
			||||||
 | 
					                                                    break;
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        finally
 | 
					                                        finally
 | 
				
			||||||
                                        {
 | 
					                                        {
 | 
				
			||||||
@@ -1693,16 +1715,20 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                        return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
 | 
					                        return formatSql(Expression.Lambda(exp).Compile().DynamicInvoke(), tsc.mapType, tsc.mapColumnTmp, tsc.dbParams);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (callExp != null) return ExpressionLambdaToSql(callExp, tsc);
 | 
					                    if (callExp != null) return ExpressionLambdaToSql(callExp, tsc);
 | 
				
			||||||
                    if (tsc.diymemexp != null)
 | 
					                    var diymemexps = new[] { tsc.diymemexp, tsc.subSelect001?._diymemexpWithTempQuery };
 | 
				
			||||||
 | 
					                    foreach (var diymemexp in diymemexps)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (diymemexp != null)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            var expStackFirst = expStack.First() as ParameterExpression;
 | 
					                            var expStackFirst = expStack.First() as ParameterExpression;
 | 
				
			||||||
                            var bidx = expStackFirst.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`") ? 2 : 1; //.Key .Value
 | 
					                            var bidx = expStackFirst.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`") ? 2 : 1; //.Key .Value
 | 
				
			||||||
                            var diyexpMembers = expStack.Where((a, b) => b >= bidx).ToArray();
 | 
					                            var diyexpMembers = expStack.Where((a, b) => b >= bidx).ToArray();
 | 
				
			||||||
                        if (diyexpMembers.Any() == false && tsc.diymemexp != null && tsc.diymemexp is Select0Provider.WithTempQueryParser tempQueryParser && tempQueryParser.GetOutsideSelectTable(expStackFirst) != null)
 | 
					                            if (diyexpMembers.Any() == false && diymemexp != null && diymemexp is Select0Provider.WithTempQueryParser tempQueryParser && tempQueryParser.GetOutsideSelectTable(expStackFirst) != null)
 | 
				
			||||||
                                diyexpMembers = expStack.ToArray();
 | 
					                                diyexpMembers = expStack.ToArray();
 | 
				
			||||||
                        var diyexpResult = tsc.diymemexp.ParseExp(diyexpMembers);
 | 
					                            var diyexpResult = diymemexp.ParseExp(diyexpMembers);
 | 
				
			||||||
                            if (string.IsNullOrEmpty(diyexpResult) == false) return diyexpResult;
 | 
					                            if (string.IsNullOrEmpty(diyexpResult) == false) return diyexpResult;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    var psgpdymes = _subSelectParentDiyMemExps.Value; //解决:分组之后的子查询解析
 | 
					                    var psgpdymes = _subSelectParentDiyMemExps.Value; //解决:分组之后的子查询解析
 | 
				
			||||||
                    if (psgpdymes?.Any() == true)
 | 
					                    if (psgpdymes?.Any() == true)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,6 +92,14 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
            to._params = new List<DbParameter>(from._params.ToArray());
 | 
					            to._params = new List<DbParameter>(from._params.ToArray());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (lambParms == null)
 | 
					            if (lambParms == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var fromTables = from._tables.Where(a => a.Type == SelectTableInfoType.Parent).ToList();
 | 
				
			||||||
 | 
					                if (fromTables.Count > 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    to._tables = new List<SelectTableInfo>(to._tables);
 | 
				
			||||||
 | 
					                    to._tables.AddRange(fromTables);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (to._tables.Count <= from._tables.Count)
 | 
					                    if (to._tables.Count <= from._tables.Count)
 | 
				
			||||||
                        to._tables = new List<SelectTableInfo>(from._tables.ToArray());
 | 
					                        to._tables = new List<SelectTableInfo>(from._tables.ToArray());
 | 
				
			||||||
@@ -102,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider
 | 
				
			|||||||
                            to._tables[a] = from._tables[a];
 | 
					                            to._tables[a] = from._tables[a];
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var findedIndexs = new List<int>();
 | 
					                var findedIndexs = new List<int>();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user