You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dynamics CRM 365插件:如何将QueryExpression应用于自定义实体列表或转LINQ?

解决方案:将QueryExpression转换为LINQ以查询内存中的Entity列表

首先明确说:你不能直接把QueryExpression实例应用到内存里的List<Entity>,因为QueryExpression是Dynamics 365 SDK专门设计给IOrganizationService.RetrieveMultiple()方法使用的查询对象,它的语法和逻辑是针对CRM后端数据存储的,无法直接作用于内存集合。

不过你完全可以把QueryExpression转换成等价的LINQ表达式,然后用它来过滤、排序你的myList。下面是具体的实现思路和示例:

核心思路:解析QueryExpression并构建LINQ表达式

QueryExpression主要包含几个关键部分:Criteria(过滤条件)、Orders(排序规则)、ColumnSet(返回列),我们需要把这些部分逐一转换成对应的LINQ操作:

1. 处理过滤条件(Criteria)

你需要遍历query.Criteria.Conditions集合,把每个ConditionExpression转换成LINQ的Where子句条件。比如一个ConditionOperator.Equal类型的条件,对应LINQ里的entity.GetAttributeValue<string>("accountname") == "Contoso"。

这里有个简化的示例方法,用来把单个ConditionExpression转换成谓词:

private static Func<Entity, bool> ConvertConditionToPredicate(ConditionExpression condition)
{
    return entity =>
    {
        var value = entity.GetAttributeValue<object>(condition.AttributeName);
        return condition.Operator switch
        {
            ConditionOperator.Equal => Equals(value, condition.Values[0]),
            ConditionOperator.GreaterThan => Comparer<object>.Default.Compare(value, condition.Values[0]) > 0,
            ConditionOperator.LessThan => Comparer<object>.Default.Compare(value, condition.Values[0]) < 0,
            // 你可以根据需要扩展更多操作符
            _ => throw new NotSupportedException($"Condition operator {condition.Operator} is not supported")
        };
    };
}

然后把所有条件组合起来(注意query.Criteria.FilterOperator是And还是Or),生成最终的Where谓词。

2. 处理排序规则(Orders)

遍历query.Orders集合,把每个OrderExpression转换成OrderBy或ThenBy操作:

IOrderedEnumerable<Entity> orderedList = query.Orders.First().OrderType == OrderType.Ascending
    ? myList.OrderBy(e => e.GetAttributeValue<object>(query.Orders.First().AttributeName))
    : myList.OrderByDescending(e => e.GetAttributeValue<object>(query.Orders.First().AttributeName));

foreach (var order in query.Orders.Skip(1))
{
    orderedList = order.OrderType == OrderType.Ascending
        ? orderedList.ThenBy(e => e.GetAttributeValue<object>(order.AttributeName))
        : orderedList.ThenByDescending(e => e.GetAttributeValue<object>(order.AttributeName));
}

3. 处理列投影(ColumnSet)

如果query.ColumnSet不是AllColumns,你可以用Select来只保留需要的属性,但因为Entity是动态类型,你可能需要创建匿名类型或者自定义DTO来存储结果:

var projectedList = orderedList.Select(e => new 
{
    AccountName = e.GetAttributeValue<string>("accountname"),
    Revenue = e.GetAttributeValue<decimal?>("revenue")
    // 根据ColumnSet里的属性逐一添加
});

注意事项

  • 复杂的QueryExpression特性(比如LinkEntity关联查询、聚合函数、嵌套过滤)很难直接转换成LINQ,因为内存列表里没有关联的实体数据,这类场景你可能需要额外处理关联逻辑。
  • 对于ConditionOperator的所有枚举值,你需要根据业务需求逐一实现转换,上面的示例只覆盖了常见的几种。
  • 如果你的列表很大,转换后的LINQ查询会在内存中执行,要注意性能问题。

完整简化示例

// 假设我们已经有了myList和query
var filteredList = myList.AsQueryable();

// 应用过滤条件
if (query.Criteria.Conditions.Any())
{
    var predicates = query.Criteria.Conditions.Select(ConvertConditionToPredicate);
    Func<Entity, bool> combinedPredicate;
    if (query.Criteria.FilterOperator == LogicalOperator.And)
    {
        combinedPredicate = e => predicates.All(p => p(e));
    }
    else
    {
        combinedPredicate = e => predicates.Any(p => p(e));
    }
    filteredList = filteredList.Where(combinedPredicate);
}

// 应用排序
if (query.Orders.Any())
{
    filteredList = ApplySorting(filteredList, query.Orders);
}

// 最终结果
var result = filteredList.ToList();

// 辅助方法:应用排序
private static IQueryable<Entity> ApplySorting(IQueryable<Entity> source, IEnumerable<OrderExpression> orders)
{
    var firstOrder = orders.First();
    var ordered = firstOrder.OrderType == OrderType.Ascending
        ? source.OrderBy(e => e.GetAttributeValue<object>(firstOrder.AttributeName))
        : source.OrderByDescending(e => e.GetAttributeValue<object>(firstOrder.AttributeName));
    
    foreach (var order in orders.Skip(1))
    {
        ordered = order.OrderType == OrderType.Ascending
            ? ordered.ThenBy(e => e.GetAttributeValue<object>(order.AttributeName))
            : ordered.ThenByDescending(e => e.GetAttributeValue<object>(order.AttributeName));
    }
    
    return ordered;
}

内容的提问来源于stack exchange,提问作者noobie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:42:20