【问题标题】:Lambda expression with .Where clause using Contains带有 .Where 子句的 Lambda 表达式使用 Contains
【发布时间】:2014-02-01 00:13:05
【问题描述】:

连接到 CRM 2013 时,是否有一种智能方法可以创建一个 lambda 表达式,该表达式可以获取列表中的 GUID 实体。

此代码在 Where 子句上中断并给出错误:

“位置”条件无效。实体成员正在调用无效的属性或方法。

代码:

    private List<UserInformationProxy> GetContactsFromGuidList(List<Guid> contactList)
    {
        var result = _serviceContext.ContactSet
            .Where(x=> contactList.Contains((Guid) x.ContactId)) // this line breaks
            .Select(x => new UserInformationProxy()
            {
                FullName = x.FullName,
                Id = x.ContactId
            })
            .Distinct()
            .ToList<UserInformationProxy>();

        return result;
    }

    // return class
    public class UserInformationProxy
    {
        public Guid? Id { get; set; }
        public string FullName { get; set; }
        public string DomainName { get; set; }
    }

目前我正在通过从 ContactSet 中获取所有联系人并在我的代码中使用循环整理出我想要的联系人来解决这个问题。这可行,但速度很慢,因为我需要获取所有 10000 个联系人,而不是将 40 个我真正感兴趣的 Guid 发送到 SQL 服务器。

【问题讨论】:

  • Equivalent to SQL IN clause 的可能重复项
  • 链接的答案没有针对此特定问题的解决方案。动态 LINQ 似乎不适用于 Guid。

标签: c# lambda dynamics-crm-2011 dynamics-crm-2013


【解决方案1】:

QueryExpressions 支持 In 运算符,因此应该可以正常工作:

private List<UserInformationProxy> GetContactsFromGuidList(List<Guid> contactList)
{
    var qe = new QueryExpression(Contact.EntityLogicalName);
    qe.ColumnSet = new ColumnSet("fullname", "contactid")
    qe.Criteria.AddCondition("contactid", ConditionOperator.In, list.Cast<Object>().ToArray());
    qe.Distinct = true;

    var results = service.RetrieveMultiple(qe).Entities.Select (e => e.ToEntity<Contact>()).
        Select(x => new UserInformationProxy()
        {
            FullName = x.FullName,
            Id = x.ContactId
        });

    return results;
}

附带说明,每个联系人的 ID 必须不为空,因此无需检查。

【讨论】:

  • 代码编译但抛出此错误:格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数schemas.microsoft.com/xrm/2011/Contracts/Services:query时出错。 InnerException 消息是“第 1 行位置 10724 中的错误。元素“schemas.microsoft.com/2003/10/Serialization/Arrays:anyType”包含映射到名称“System.Collections.Generic:List`1”的类型的数据。反序列化器不知道映射到此名称的任何类型。 .
  • @JensBerfenfeldt 抱歉,我们有一些扩展方法可以让这段代码更简单,我试图从头开始。我已经用处理从 List 到 Object[] 的转换的正确方法更新了我的答案。我对其进行了测试,所以它应该可以工作:) AddCondition 接受一个参数对象 [],并且列表被视为单个对象,而不是列表,因此调用将其转换为对象,然后转换为一个数组解决了这个问题。
  • 附带说明,您需要将要使用的列添加到 QueryExpression,即:qe.ColumnSet = new ColumnSet("fullname", "contactid");否则你只会得到空值。
  • 感谢@Daryl 分享这些信息,我知道In 子句,但我认为它不适用于记录Guid
  • @JensBerfenfeldt 不错。
【解决方案2】:

编辑:可以使用单个查询来完成,Daryl 使用正确的代码发布了答案。

其他(不那么聪明的)替代方案是:

  1. 检索所有记录并检查指南后
  2. 为每个 Guid 进行一次检索

因为只有40条记录,建议使用late-bound来检索记录,以便选择最小的ColumnSet。

与此问题相关的有用链接:

【讨论】:

  • 与获取全部并在代码中进行排序相比,您认为对每个帖子进行单次检索的性能断点是什么时候?
  • 确定断点并不容易,但我建议使用后期绑定,因为在您的情况下,对于少数记录而言,它比早期绑定更快,您可以在此处找到分析:woodsworkblog.wordpress.com/2013/02/25/…
猜你喜欢
  • 1970-01-01
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多