diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index 5d437904..0572a531 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -15,6 +15,13 @@ namespace Sample.MySql.Controllers public string Id { get; set; } public int C { get; set; } } + + public class abc + { + public string id { get; set; } + public string name { get; set; } + public int count { get; set; } + } [ApiController] [Route("[controller]/[action]")] public class WeatherForecastController : ControllerBase @@ -58,6 +65,24 @@ namespace Sample.MySql.Controllers // Console.WriteLine("------------"); // using (var tran = _defaultTableDbContext.Database.BeginTransaction()) // { + var resultX1 = await _defaultTableDbContext.Set() + .Where(o => o.Id == "2" || o.Id == "3").GroupBy(o => new { o.Id,o.Name }) + .Select(o => new + { + id = o.Key.Id, + name = o.Key.Name, + count = o.Count() + }).ToListAsync(); + var resultX12 = await _defaultTableDbContext.Set() + .Where(o => o.Id == "2" || o.Id == "3").GroupBy(o => new { o.Id,o.Name }) + .Select(o => new abc + { + id = o.Key.Id, + name = o.Key.Name, + count = o.Count() + }).ToListAsync(); + + var firstOrDefault = _defaultTableDbContext.Set().FromSqlRaw($"select * from {nameof(SysUserMod)}").FirstOrDefault(); var sysUserMods1 = _defaultTableDbContext.Set() diff --git a/src/ShardingCore/Extensions/ExpressionExtension.cs b/src/ShardingCore/Extensions/ExpressionExtension.cs index 4ac22767..d4dfb8a7 100644 --- a/src/ShardingCore/Extensions/ExpressionExtension.cs +++ b/src/ShardingCore/Extensions/ExpressionExtension.cs @@ -25,10 +25,6 @@ namespace ShardingCore.Extensions throw new Exception($"type:{typeof(T)} not found [{name}] properity "); } - var param_obj = Expression.Parameter(type); - var param_val = Expression.Parameter(typeof(object)); - var body_obj = Expression.Convert(param_obj, type); - var body_val = Expression.Convert(param_val, p.PropertyType); //获取设置属性的值的方法 var setMethod = p.GetSetMethod(true); @@ -36,6 +32,10 @@ namespace ShardingCore.Extensions //如果只是只读,则setMethod==null if (setMethod != null) { + var param_obj = Expression.Parameter(type); + var param_val = Expression.Parameter(typeof(object)); + var body_obj = Expression.Convert(param_obj, type); + var body_val = Expression.Convert(param_val, p.PropertyType); var body = Expression.Call(param_obj, p.GetSetMethod(), body_val); var setValue = Expression.Lambda>(body, param_obj, param_val).Compile(); setValue(t, value); diff --git a/src/ShardingCore/Extensions/TypeExtension.cs b/src/ShardingCore/Extensions/TypeExtension.cs index 13e1ab07..c356d723 100644 --- a/src/ShardingCore/Extensions/TypeExtension.cs +++ b/src/ShardingCore/Extensions/TypeExtension.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -87,5 +89,16 @@ namespace ShardingCore.Extensions return Type.GetTypeCode(type) == TypeCode.Boolean; } + public static bool IsAnonymousType(this Type type) + { + if (type == null) + throw new ArgumentNullException(nameof(type)); + + // HACK: The only way to detect anonymous types right now. + return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false) + && type.IsGenericType && type.Name.Contains("AnonymousType") + && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$")) + && type.Attributes.HasFlag(TypeAttributes.NotPublic); + } } } diff --git a/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs b/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs index 96173542..83c461b4 100644 --- a/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs +++ b/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs @@ -25,14 +25,36 @@ namespace ShardingCore.Sharding.Enumerators.AggregateExtensions var anonType = source.GetType(); var allProperties = anonType.GetProperties(); var allPropertyTypes= allProperties.Select(o=>o.PropertyType).ToArray(); - var constantExpressions = allProperties.Select(o => Expression.Constant(o.GetValue(source))).ToArray(); + if (anonType.IsAnonymousType()) + { + var constantExpressions = allProperties.Select(o => Expression.Constant(o.GetValue(source))).ToArray(); + var exp = Expression.New( + anonType.GetConstructor(allPropertyTypes), + constantExpressions); + var lambda = LambdaExpression.Lambda(exp); + TSource myObj = (TSource)lambda.Compile().DynamicInvoke(); + return myObj; + } + else + { + var parameters = allProperties.Select(o => o.GetValue(source)).ToArray(); + if (anonType.GetConstructors().Length == 1 && + anonType.GetConstructors()[0].GetParameters().Length == allPropertyTypes.Length) + { + return (TSource)Activator.CreateInstance(anonType, parameters); + } + else + { + var instance = (TSource)Activator.CreateInstance(anonType); + foreach (var property in allProperties) + { + var value = property.GetValue(source); + instance.SetPropertyValue(property.Name,value); + } - var exp = Expression.New( - anonType.GetConstructor(allPropertyTypes), - constantExpressions); - var lambda = LambdaExpression.Lambda(exp); - TSource myObj = (TSource)lambda.Compile().DynamicInvoke(); - return myObj; + return instance; + } + } } [ExcludeFromCodeCoverage] diff --git a/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs b/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs index a6a39259..fe166fe9 100644 --- a/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs +++ b/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs @@ -125,6 +125,21 @@ namespace ShardingCore.Core.Internal.Visitors var propertyInfo = declaringType.GetProperty(memberName); _selectContext.SelectProperties.Add(new SelectOwnerProperty(declaringType, propertyInfo)); //memberExpression.Acc + }else if (expression is MemberInitExpression memberInitExpression) + { + foreach (var memberBinding in memberInitExpression.Bindings) + { + if (memberBinding is MemberAssignment memberAssignment) + { + if (memberAssignment.Expression is MemberExpression bindMemberExpression) + { + var declaringType = memberBinding.Member.DeclaringType; + var memberName = memberBinding.Member.Name; + var propertyInfo = declaringType.GetProperty(memberName); + _selectContext.SelectProperties.Add(new SelectOwnerProperty(declaringType, propertyInfo)); + } + } + } } //if (expression != null) //{