在分组依据中使用表达式树后无法选择

时间:2015-03-18 11:00:29

标签: c# linq linq-to-sql lambda expression-trees

我一直使用表达式树将this post引用到组。这是我的代码:

String[] fields = { "DepartmentID", "SkillID" };
var groupLambda = GroupByExpression<Person>(fields);
var query = dbContext.People.GroupBy(groupLambda.Compile());
var queryResult = query.ToList();

以下方法GroupByExpression使用上述帖子中给出的解决方案(谢谢Daniel!):

public static Expression<Func<TItem, object>> GroupByExpression<TItem>(string[] propertyNames)
{
var properties = propertyNames.Select(name => typeof(TItem).GetProperty(name)).ToArray();
var propertyTypes = properties.Select(p => p.PropertyType).ToArray();
var tupleTypeDefinition = typeof(Tuple).Assembly.GetType("System.Tuple`" + properties.Length);
var tupleType = tupleTypeDefinition.MakeGenericType(propertyTypes);
var constructor = tupleType.GetConstructor(propertyTypes);
var param = Expression.Parameter(typeof(TItem), "x");
var body = Expression.New(constructor, properties.Select(p => Expression.Property(param, p)));
var expr = Expression.Lambda<Func<TItem, object>>(body, param);
return expr;
}

我希望能够通过选择部分中具有强名称的键来识别组中的字段,例如 query.Select(x => new { x.Key.DepartmentID, x.Key.SkillID });

我该怎么做?

2 个答案:

答案 0 :(得分:3)

现在......我不会给你解决问题的方法,但我会尽力帮助你: - )

如果要进行动态查询,则应该使用DynamicLinq

使用DynamicLinq,您可以执行以下操作:

IQueryable query = context.YourTable;
var groups = query.GroupBy("new (Field1, Field2)");

我正在重读你的问题......

  

我希望能够通过在查询等选择部分中具有强名称的键来识别组中的字段。选择(x =&gt; new {x.Key.DepartmentID,x.Key.SkillID});

你不能。 GroupBy一般会返回IGrouping<TKey, TSource>TKey是动态的(因为您是根据字符串构建的),因此您无法提取&#34;它并将其传递给编译器,因此您无法使用强名称进行选择。

只有一个例外:如果您知道GroupBy TKey的类型和编号,那么可以做一些事情。所以,你给了我们:

String[] fields = { "DepartmentID", "SkillID" };

如果您总是有两个 int ,那么您可以使用以下方式投射查询:

.Cast<IGrouping<Tuple<int, int>, Person>>()
.Select(x => new { x.Key.DepartmentID, x.Key.SkillID });

请注意,正如我在评论中写的那样,GroupBy将在客户端执行,而GroupBy之后的所有内容都将在客户端执行(客户端) ==你的程序是vs sql-side ==你的sql服务器在哪里)!

DynamicLinq 解决执行查询sql-side而不是客户端的问题,但won't解决了强命令与弱命名问题(在DynamicLinq之后)您可以:A)使用.Cast<>()方法或B)返回dynamic对象/ IEnumerable<dynamic>

答案 1 :(得分:0)

您正在使用的语法new { x.Key.DepartmentID, x.Key.SkillID }在编译时构造一个匿名类。如果要在运行时创建匿名类,请参阅here。但是,这将不允许您“通过具有强名称的键识别组中的字段”。如果你想在运行时构造一个匿名类,但能够在编译时使用这些名称,我担心这是不可能的。