繁体   English   中英

如何在运行时使用具有不同类型的多个group by子句构建linq查询

[英]How can I build a linq query at runtime with multiple group by clauses with different types

我处于一种需要在运行时对EF上下文指定查询的情况。 我们的顾问会在客户现场针对客户的特定情况配置这些查询。

为了方便起见,我正在考虑使用linq来构建查询,这些查询基于顾问在某种前端(现在是winforms)中指定的标准列表。 顾问基本上从对象中指定属性,然后指定运算符和值。 例如:给我所有的客户[状态] [等于] [1]。

目前,我有一个表达式生成器,可以在运行时创建where子句,到目前为止,我可以管理一个group by子句。 我在这里碰壁的地方是顾问配置多个不同类型的group by子句(例如字符串和datetime属性)。

例如,我必须能够处理此查询:从状态= 1按bsn分组的客户端,dateofbirth(其中bsn =字符串且dateofbirth = datetime)的客户端中,选择bsn作为a,dateofbirth作为b。

目前,这是将查询“粘合”在一起的代码:

public List<ClientV2> ExportClients(List<CriteriaV2> criteriaList)
{
    var whereExpression = BuildWhereExpressionChain(criteriaList.Where(c => c.Operator != CriteriaOperatorV2.GROUPBY).ToList());

    var groupByExpression = BuildGroupByExpression(criteriaList.Where(c => c.Operator == CriteriaOperatorV2.GROUPBY).ToList());

    var sourceClients = _context.Clients.Where(whereExpression).GroupBy(groupByExpression).ToList();

    IEnumerable<Client> resultClients = sourceClients.SelectMany(group => group);

    return ClientToClientV2.MapList(resultClients.ToList());
}

这是子句构建器:

private Expression<Func<Client, bool>> BuildWhereExpressionChain(List<CriteriaV2> criteriaList)
{
    var expressionList = new List<Expression<Func<Client, bool>>>();
    var paramExp = Expression.Parameter(typeof(Client));

    foreach (var crit in criteriaList)
    {
        var propertyItem = PropertyTranslator.GetPropertyItem(crit.Property);
        if (propertyItem == null) throw new InvalidFilterCriteriaException("Property " + crit.Property + " niet toegestaan als filter criterium");

        var propInfo = typeof(Client).GetProperty(propertyItem.InternalName);
        var left = Expression.Property(paramExp, propInfo);
        Expression right;

        if (propInfo.PropertyType.IsEnum)
            right = Expression.Constant(Enum.ToObject(propInfo.PropertyType, PropertyTranslator.TranslateEnum(propertyItem.Type, crit.Value)));
        else if (propInfo.PropertyType == typeof(DateTime) || propInfo.PropertyType == typeof(DateTime?))
            right = Expression.Constant(DateTime.Parse(crit.Value), propInfo.PropertyType);
        else
            right = Expression.Constant(crit.Value, typeof(string));

        var exp = BuildExpression(left, right, crit.Operator);

        expressionList.Add(Expression.Lambda<Func<Client, bool>>(exp, new ParameterExpression[] { paramExp }));
    }

    var firstExpression = expressionList.First();
    expressionList.Skip(1).ToList().ForEach(ex => { firstExpression = firstExpression.And(ex); });

    return firstExpression;
}

这就是我卡住的部分(它确实适用于字符串类型的一个子句):

private Expression<Func<Client, string>> BuildGroupByExpression(List<CriteriaV2> criteriaList)
{
    var expressionList = new List<Expression<Func<Client, string>>>();
    var paramExp = Expression.Parameter(typeof(Client));

    foreach (var crit in criteriaList)
    {
        var propertyItem = PropertyTranslator.GetPropertyItem(crit.Property);
        if (propertyItem == null) throw new InvalidFilterCriteriaException("Property " + crit.Property + " niet toegestaan als group by criterium");

        var propInfo = typeof(Client).GetProperty(propertyItem.InternalName);
        var body = Expression.Property(paramExp, propInfo);
        var lambda = Expression.Lambda<Func<Client, string>>(body, paramExp);
        expressionList.Add(lambda);
    }

    var firstExpression = expressionList.First();
    expressionList.Skip(1).ToList().ForEach(ex => { firstExpression = firstExpression.And(ex); });

    return firstExpression;
}

是否有可能使BuildGroupByExpression()产生一个表达式,该表达式包含多个不同类型的子句,我可以直接在.GroupBy(expression);中使用该子句?

我不是linq的专家,但是我有一种自己想要的东西。 如果我在这里做愚蠢的事情,请指出来,我会继续努力。

我不这么认为。 至少使用构建表达式的方法,您将拥有自己的方式。 至少我最终为每种类型构建了表达式。 主要原因是

  var lambda = Expression.Lambda<Func<Client, string>>(body, paramExp);

我不知道如何使此Lambda定义动态或通用。

有一种不同的方法,一个库在运行时使用字符串解释来构建表达式。 看到

Install-Package System.Linq.Dynamic.Library

另请参见https://msdn.microsoft.com/zh-CN/vstudio/bb894665.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM