mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	- 修复 多对多导航属性 AsSelect() 无法使用 .Count() 的问题;#362
This commit is contained in:
		@@ -486,5 +486,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>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,6 +111,12 @@ namespace FreeSql.Tests.SqlServer
 | 
				
			|||||||
            //		WHERE(t.[Name] = '国语') AND(t.[Id] = Mt_Ms.[Tag_id])
 | 
					            //		WHERE(t.[Name] = '国语') AND(t.[Id] = Mt_Ms.[Tag_id])
 | 
				
			||||||
            //		limit 0, 1))
 | 
					            //		limit 0, 1))
 | 
				
			||||||
            //	limit 0, 1))
 | 
					            //	limit 0, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var t3 = g.sqlserver.Select<Song>().ToList(r => new
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                r.Title,
 | 
				
			||||||
 | 
					                count = r.Tags.AsSelect().Count()
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,6 +107,17 @@ namespace FreeSql.Tests.Sqlite
 | 
				
			|||||||
            //		WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`)
 | 
					            //		WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`)
 | 
				
			||||||
            //		limit 0, 1))
 | 
					            //		limit 0, 1))
 | 
				
			||||||
            //	limit 0, 1))
 | 
					            //	limit 0, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var t3 = g.sqlite.Select<Song>().ToList(r => new
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                r.Title,
 | 
				
			||||||
 | 
					                count = r.Tags.AsSelect().Count(),
 | 
				
			||||||
 | 
					                //sum = r.Tags.AsSelect().Sum(b => b.Id + 0),
 | 
				
			||||||
 | 
					                //avg = r.Tags.AsSelect().Avg(b => b.Id + 1),
 | 
				
			||||||
 | 
					                //max = r.Tags.AsSelect().Max(b => b.Id + 2),
 | 
				
			||||||
 | 
					                //min = r.Tags.AsSelect().Min(b => b.Id + 3),
 | 
				
			||||||
 | 
					                //first = r.Tags.AsSelect().First(b => b.Name)
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -426,7 +426,7 @@ namespace FreeSql.Internal
 | 
				
			|||||||
        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
					        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
				
			||||||
        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
					        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
				
			||||||
        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
					        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
				
			||||||
        static ConcurrentDictionary<Type, MethodInfo> _dicExpressionLambdaToSqlAsSelectAnyMethodInfo = new ConcurrentDictionary<Type, MethodInfo>();
 | 
					        static ConcurrentDictionary<Type, ConcurrentDictionary<string, MethodInfo>> _dicExpressionLambdaToSqlAsSelectAggMethodInfo = new ConcurrentDictionary<Type, ConcurrentDictionary<string, MethodInfo>>();
 | 
				
			||||||
        internal static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>();
 | 
					        internal static ConcurrentDictionary<Type, PropertyInfo> _dicNullableValueProperty = new ConcurrentDictionary<Type, PropertyInfo>();
 | 
				
			||||||
        static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>();
 | 
					        static ConcurrentDictionary<Type, Expression> _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary<Type, Expression>();
 | 
				
			||||||
        static MethodInfo MethodDateTimeSubtractDateTime = typeof(DateTime).GetMethod("Subtract", new Type[] { typeof(DateTime) });
 | 
					        static MethodInfo MethodDateTimeSubtractDateTime = typeof(DateTime).GetMethod("Subtract", new Type[] { typeof(DateTime) });
 | 
				
			||||||
@@ -915,8 +915,8 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                        var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 =>
 | 
					                                        var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 =>
 | 
				
			||||||
                                            typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] {
 | 
					                                            typeof(ISelect<>).MakeGenericType(asSelectEntityType3).GetMethod("Where", new[] {
 | 
				
			||||||
                                            typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool)))
 | 
					                                                typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(asSelectEntityType3, typeof(bool)))
 | 
				
			||||||
                                        }));
 | 
					                                            }));
 | 
				
			||||||
                                        var parm123Tb = _common.GetTableByEntity(asSelectParentExp.Type);
 | 
					                                        var parm123Tb = _common.GetTableByEntity(asSelectParentExp.Type);
 | 
				
			||||||
                                        var parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true);
 | 
					                                        var parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true);
 | 
				
			||||||
                                        if (parm123Ref != null)
 | 
					                                        if (parm123Ref != null)
 | 
				
			||||||
@@ -929,12 +929,10 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                                                var manyTb = _common.GetTableByEntity(parm123Ref.RefMiddleEntityType);
 | 
					                                                var manyTb = _common.GetTableByEntity(parm123Ref.RefMiddleEntityType);
 | 
				
			||||||
                                                var manySubSelectWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
					                                                var manySubSelectWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
				
			||||||
                                                    typeof(ISelect<>).MakeGenericType(refMiddleEntityType3).GetMethod("Where", new[] {
 | 
					                                                    typeof(ISelect<>).MakeGenericType(refMiddleEntityType3).GetMethod("Where", new[] {
 | 
				
			||||||
                                            typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(refMiddleEntityType3, typeof(bool)))
 | 
					                                                        typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(refMiddleEntityType3, typeof(bool)))
 | 
				
			||||||
                                                }));
 | 
					                                                    }));
 | 
				
			||||||
                                                var manySubSelectWhereSql = _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
					                                                var manySubSelectWhereSql = _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
				
			||||||
                                                    typeof(ISelect0<,>).MakeGenericType(typeof(ISelect<>).MakeGenericType(refMiddleEntityType3), refMiddleEntityType3).GetMethod("Where", new[] { typeof(string), typeof(object) }));
 | 
					                                                    typeof(ISelect0<,>).MakeGenericType(typeof(ISelect<>).MakeGenericType(refMiddleEntityType3), refMiddleEntityType3).GetMethod("Where", new[] { typeof(string), typeof(object) }));
 | 
				
			||||||
                                                var manySubSelectAny = _dicExpressionLambdaToSqlAsSelectAnyMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
					 | 
				
			||||||
                                                    typeof(ISelect0<,>).MakeGenericType(typeof(ISelect<>).MakeGenericType(refMiddleEntityType3), refMiddleEntityType3).GetMethod("Any", new Type[0]));
 | 
					 | 
				
			||||||
                                                var manySubSelectAsSelectExp = _dicFreeSqlGlobalExtensionsAsSelectExpression.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
					                                                var manySubSelectAsSelectExp = _dicFreeSqlGlobalExtensionsAsSelectExpression.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 =>
 | 
				
			||||||
                                                    Expression.Call(
 | 
					                                                    Expression.Call(
 | 
				
			||||||
                                                        typeof(FreeSqlGlobalExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(mfil => mfil.Name == "AsSelect" && mfil.GetParameters().Length == 1).FirstOrDefault()?.MakeGenericMethod(refMiddleEntityType3),
 | 
					                                                        typeof(FreeSqlGlobalExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(mfil => mfil.Name == "AsSelect" && mfil.GetParameters().Length == 1).FirstOrDefault()?.MakeGenericMethod(refMiddleEntityType3),
 | 
				
			||||||
@@ -987,9 +985,25 @@ namespace FreeSql.Internal
 | 
				
			|||||||
                                                var sql2 = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { "1" })?.ToString();
 | 
					                                                var sql2 = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { "1" })?.ToString();
 | 
				
			||||||
                                                if (string.IsNullOrEmpty(sql2) == false)
 | 
					                                                if (string.IsNullOrEmpty(sql2) == false)
 | 
				
			||||||
                                                    manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectWhereSql, Expression.Constant($"exists({sql2.Replace("\r\n", "\r\n\t")})"), Expression.Constant(null));
 | 
					                                                    manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectWhereSql, Expression.Constant($"exists({sql2.Replace("\r\n", "\r\n\t")})"), Expression.Constant(null));
 | 
				
			||||||
                                                manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectAny);
 | 
					                                                MethodInfo manySubSelectAggMethod = null;
 | 
				
			||||||
 | 
					                                                switch (exp3.Method.Name) //https://github.com/dotnetcore/FreeSql/issues/362
 | 
				
			||||||
 | 
					                                                {
 | 
				
			||||||
 | 
					                                                    case "Any":
 | 
				
			||||||
 | 
					                                                    case "Count":
 | 
				
			||||||
 | 
					                                                        manySubSelectAggMethod = _dicExpressionLambdaToSqlAsSelectAggMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, _ => new ConcurrentDictionary<string, MethodInfo>()).GetOrAdd(exp3.Method.Name, exp3MethodName =>
 | 
				
			||||||
 | 
					                                                            typeof(ISelect0<,>).MakeGenericType(typeof(ISelect<>).MakeGenericType(parm123Ref.RefMiddleEntityType), parm123Ref.RefMiddleEntityType).GetMethod(exp3MethodName, new Type[0]));
 | 
				
			||||||
 | 
					                                                        manySubSelectExpBoy = Expression.Call(manySubSelectExpBoy, manySubSelectAggMethod);
 | 
				
			||||||
 | 
					                                                        break;
 | 
				
			||||||
 | 
					                                                    case "Sum":
 | 
				
			||||||
 | 
					                                                    case "Min":
 | 
				
			||||||
 | 
					                                                    case "Max":
 | 
				
			||||||
 | 
					                                                    case "Avg":
 | 
				
			||||||
 | 
					                                                    case "ToList":
 | 
				
			||||||
 | 
					                                                    case "ToOne":
 | 
				
			||||||
 | 
					                                                    case "First":
 | 
				
			||||||
 | 
					                                                        throw new ArgumentException($"ManyToMany 导航属性 .AsSelect() 暂时不可用于 Sum/Avg/Max/Min/First/ToOne/ToList 方法");
 | 
				
			||||||
 | 
					                                                }
 | 
				
			||||||
                                                asSelectBefores.Clear();
 | 
					                                                asSelectBefores.Clear();
 | 
				
			||||||
 | 
					 | 
				
			||||||
                                                return ExpressionLambdaToSql(manySubSelectExpBoy, tsc);
 | 
					                                                return ExpressionLambdaToSql(manySubSelectExpBoy, tsc);
 | 
				
			||||||
                                            }
 | 
					                                            }
 | 
				
			||||||
                                            for (var mn = 0; mn < parm123Ref.Columns.Count; mn++)
 | 
					                                            for (var mn = 0; mn < parm123Ref.Columns.Count; mn++)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user