Dynamics CRM SDK - 带有OrganizationServiceContext的linq的IN运算符

dynamics-crm-2011 dynamics-crm

3530 观看

4回复

773 作者的声誉

我正在使用svcutil生成的OrganizationServiceContext实现来从CRM中检索实体:

context.new_productSet.First(p => p.new_name == "Product 1");

是否可以一次检索具有不同属性值的多个实体 - (像SQL中的IN运算符一样)?

示例:我想通过一次调用检索多个产品(“产品1”,“产品2”,...)。产品名称列表是动态的,存储在名为productNames的数组中。

作者: filip 的来源 发布者: 2014 年 3 月 11 日

回应 (4)


0

1746 作者的声誉

我不知道如何用Linq做到这一点,据我所知,这是不可能的。

可以使用Query Expressions完成:

String[] productNames = new[] { "test1", "test2" };
QueryExpression products = new QueryExpression(Product.EntityLogicalName);
products.ColumnSet = new ColumnSet("name", "new_att1", "new_att2"); // fields to get 
products.Criteria.AddCondition("name", ConditionOperator.In,
    productNames.Cast<Object>().ToArray()); // filter by array
EntityCollection res = service.RetrieveMultiple(products);
IEnumerable<Product> opportunities = res.Entities
    .Select(product => product.ToEntity<Product>()); // you can use Linq again from here
作者: Bvrce 发布者: 11.03.2014 02:34

7

20585 作者的声誉

决定

不,你不能。CRM LINQ提供程序仅允许变量出现在表达式的左侧,而右侧必须包含常量。

Product.Where(e => e.Name == desiredName)

不支持也不会工作(它会抱怨在比较的右侧使用变量)。

如果你无法避免这种类型的查询,你必须.ToList()首先获得数据(这可能导致一个巨大的结果集,并且可能会变得非常慢):

Product.ToList().Where(e => e.Name == desiredName)

这将有效,因为现在.Where()正在应用List<>

另一种方法(我没有关于性能的数据)是创建许多查询,基本上一次获取一个记录:

// ... this is going to be a nightmare ... don't do it ...
var entities = new List<Product>();
entities.Add(Product.Where(e => e.Name == "Product 1"));
entities.Add(Product.Where(e => e.Name == "Product 2"));

或者使用QueryExpression这样的(我个人最喜欢的,因为我总是迟到)

var desiredNames = new string[]{"Product 1", "Product 2"};
var filter = new FilterExpression(LogicalOperator.And)
{
    Conditions = 
    {
        new ConditionExpression("name", ConditionOperator.In, desiredNames)
    }
};
var query = new QueryExpression(Product.EntityLogicalName)
{
    ColumnSet = new ColumnSet(true),
    Criteria = filter
};
var records = service.RetrieveMultiple(query).Entities;
作者: Alex 发布者: 11.03.2014 02:38

2

21 作者的声誉

使用QueryExpression时,我们可以为where子句添加condtionexpression。ConditionExpression采用ConditionOperator枚举器,我们可以使用ConditionOperator.In。下面是使用“In”运算符启动conidtionExpression的方法,第三个参数可以是数组或集合。

ConditionExpression ce = new ConditionExpression("EntityName",
        ConditionOperator.In, collectionObject);

请参阅下面的进一步说明。

http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.query.conditionexpression.conditionexpression.aspx

作者: user3406717 发布者: 11.03.2014 02:46

0

83 作者的声誉

如果组合Linq和Lambda表达式没问题,可以完成。首先,您需要创建一个扩展方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Kipon.Dynamics.Extensions.IQueryable
{
    public static class Methods
    {
        public static IQueryable<TSource> WhereIn<TSource, TValue>(this IQueryable<TSource> source, Expression<Func<TSource, TValue>> valueSelector, IEnumerable<TValue> values)
        {
            if (null == source) { throw new ArgumentNullException("source"); }
            if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
            if (null == values) { throw new ArgumentNullException("values"); }

            var equalExpressions = new List<BinaryExpression>();

            foreach (var value in values)
            {
                var equalsExpression = Expression.Equal(valueSelector.Body, Expression.Constant(value));
                equalExpressions.Add(equalsExpression);
            }

            ParameterExpression p = valueSelector.Parameters.Single();
            var combined = equalExpressions.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
            var combinedLambda = Expression.Lambda<Func<TSource, bool>>(combined, p);

            return source.Where(combinedLambda);
        }
    }
}

有了这个方法,您现在可以根据您的上下文使用它。首先请记住导入扩展名的名称空间,以使该方法在IQueryable上可用:

using System.Linq;
using Kipon.Dynamics.Extensions.IQueryable;

public class MyClass
  {
     void myQueryMethod(CrmContext ctx, Guid[] contacts) 
     {
       var accounts = (from a in ctx.accountSet.WhereIn(ac => ac.primarycontactid.id,contacts)
                       where a.name != null
                       select a).toArray();
     }
}

据我所知,您无法挂钩到Dynamics 365 Linq表达式编译器,但上述代码将在针对CRM的一个请求中执行,并利用您不需要考虑分页等事实与Linq合作时。

如您所见,whereIn子句添加了lambda样式表达式,其中查询的其余部分使用Linq样式。

作者: Kjeld Poulsen 发布者: 29.08.2019 05:52
32x32