fil*_*lip 2 dynamics-crm dynamics-crm-2011
我正在使用svcutil生成的OrganizationServiceContext实现来从CRM中检索实体:
context.new_productSet.First(p => p.new_name == "Product 1");
是否可以一次检索具有不同属性值的多个实体 - (像SQL中的IN运算符一样)?
示例:我想通过一次调用检索多个产品("产品1","产品2",...).产品名称列表是动态的,存储在名为productNames的数组中.
不,你不能.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;
如果结合 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 样式。
| 归档时间: | 
 | 
| 查看次数: | 3677 次 | 
| 最近记录: |