diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 474ea8d5..4854f49c 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -486,5 +486,14 @@ + + + 批量注入 Repository,可以参考代码自行调整 + + + + + + diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index de245c0c..48d87b2c 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -111,6 +111,12 @@ namespace FreeSql.Tests.SqlServer // WHERE(t.[Name] = '国语') AND(t.[Id] = Mt_Ms.[Tag_id]) // limit 0, 1)) // limit 0, 1)) + + var t3 = g.sqlserver.Select().ToList(r => new + { + r.Title, + count = r.Tags.AsSelect().Count() + }); } [Fact] diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 7ec386cc..e7201fb6 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -107,6 +107,17 @@ namespace FreeSql.Tests.Sqlite // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) // limit 0, 1)) // limit 0, 1)) + + var t3 = g.sqlite.Select().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] diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index 8ca5c1c0..6a8cda46 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -426,7 +426,7 @@ namespace FreeSql.Internal static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectMethodInfo = new ConcurrentDictionary(); static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereMethodInfo = new ConcurrentDictionary(); static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectWhereSqlMethodInfo = new ConcurrentDictionary(); - static ConcurrentDictionary _dicExpressionLambdaToSqlAsSelectAnyMethodInfo = new ConcurrentDictionary(); + static ConcurrentDictionary> _dicExpressionLambdaToSqlAsSelectAggMethodInfo = new ConcurrentDictionary>(); internal static ConcurrentDictionary _dicNullableValueProperty = new ConcurrentDictionary(); static ConcurrentDictionary _dicFreeSqlGlobalExtensionsAsSelectExpression = new ConcurrentDictionary(); static MethodInfo MethodDateTimeSubtractDateTime = typeof(DateTime).GetMethod("Subtract", new Type[] { typeof(DateTime) }); @@ -915,8 +915,8 @@ namespace FreeSql.Internal } var fsqlWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(asSelectEntityType, asSelectEntityType3 => 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 parm123Ref = parm123Tb.GetTableRef(asSelectParentExp1.Member.Name, true); if (parm123Ref != null) @@ -929,12 +929,10 @@ namespace FreeSql.Internal var manyTb = _common.GetTableByEntity(parm123Ref.RefMiddleEntityType); var manySubSelectWhere = _dicExpressionLambdaToSqlAsSelectWhereMethodInfo.GetOrAdd(parm123Ref.RefMiddleEntityType, refMiddleEntityType3 => 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 => 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 => Expression.Call( 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(); 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, 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()).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(); - return ExpressionLambdaToSql(manySubSelectExpBoy, tsc); } for (var mn = 0; mn < parm123Ref.Columns.Count; mn++)