按动态分组多列

时间:2014-07-23 09:35:42

标签: entity-framework linq-to-sql group-by

有没有办法动态分组多列?

EG。 group x by new { x.Column1, x.Column2 }

x.Column1等我想动态设置(来自UI)

1 个答案:

答案 0 :(得分:0)

在db站点上动态实现这一点的方法非常复杂,因为我们无法动态创建匿名类型。要替换它们,我建议创建一个类:

public class CustomTuple<T1, T2>
{
    public T1 Item1 { get; set; }
    public T2 Item2 { get; set; }
}

我们不能在这里使用Tuple,因为它没有默认构造函数。在CustomTuple类中,尽可能多地放置参数T和尽可能多的属性。如果您将在该类中定义5个属性,但对于查询,您将仅使用3个,您只需将3个属性设置为正确的值,而其余2个属性保留为null - 查询仍然有效。或者,您可以在运行时动态生成CodeDOM正确的类。然后是查询逻辑:

Type[] parameterTypes = new Type[] { typeof(int), typeof(object) };
Type tupleType = typeof(CustomTuple<,>).MakeGenericType(parameterTypes);
ParameterExpression x = Expression.Parameter(typeof(Entity));
NewExpression body = Expression.New(tupleType.GetConstructor(new Type[0]), new Expression[0]);
MemberBinding binding1 = Expression.Bind(
    typeof(CustomTuple<,>).MakeGenericType(parameterTypes).GetProperty("Item1"),
    Expression.Property(x, "Value"));
MemberInitExpression memberInitExpression =
    Expression.MemberInit(
        body,
        binding1);

Expression<Func<Entity, object>> exp = Expression.Lambda<Func<Entity, object>>(memberInitExpression, x);
using (MyDbContext context = new MyDbContext())
{
    var list = context.Entities.GroupBy(exp).ToList();
}

上面的代码按实体属性分组实体。 parameterTypes可以在程序执行期间动态构建 - 这是一组匿名类型的属性列表,用于组中的键选择。基于此我们创建适当的CustomTuple类型。然后我们在运行时动态创建binding1元素 - 每个属性一个用于分组键。在上面的例子中,我只创建了一个。通过使用NewExpression和MemberBinding表达式,我们可以使用MemberInit方法构建初始化表达式。最后,你从中构建lambda表达式并对db。

执行它