【问题标题】:Linq To CRM IQueryable IssueLinq To CRM IQueryable 问题
【发布时间】:2015-01-14 14:02:18
【问题描述】:

我正在尝试动态过滤 Linq-To-CRM 中的查询结果。

基本上我有一个标准查询,然后基于某些标准,我希望能够向其中添加某些过滤器。但是,我收到此错误... 方法“Where”不能跟随方法“Select”或不受支持。尝试根据支持的方法编写查询,或在调用不受支持的方法之前调用“AsEnumerable”或“ToList”方法。

我的代码的简化示例如下所示。任何人都知道这是否可以使用 linq-to-sql 来完成? 我可能有 5 或 6 个单独的过滤器,我可能需要也可能不需要动态添加。我当然可以为过滤器的所有可能组合定义单独的查询,但这似乎有点矫枉过正,我想尽可能避免这种情况。

IQueryable<CourseProduct> coursesVar =
(
    from a in context.CreateQuery("vs_course")
    join b in context.CreateQuery("product") on a["vs_product"] equals b["productid"]
    join c in context.CreateQuery("productpricelevel") on b["productid"] equals c["productid"]
    join d in context.CreateQuery("vs_coursetype") on a["vs_coursetype"] equals d["vs_coursetypeid"]
    join e in context.CreateQuery("vs_coursearea") on a["vs_coursearea"] equals e["vs_courseareaid"]
    where a["vs_product"] != null // ensure product is set
    && a["vs_coursetype"] != null
    && a["vs_coursearea"] != null
    && a["vs_price"] != null
    where b["price"] != null
    where c["pricelevelid"] != null
    && (Guid)c["pricelevelid"] == pricelistId // ensure price list is set (and matches the correct pricelist)
    && c["amount"] != null
    select new CourseProduct
    {
        CourseId = (Guid)a["vs_courseid"],
        CourseCode = !a.Contains("vs_code") ? string.Empty : (string)a["vs_code"],
        CourseName = !a.Contains("vs_name") ? string.Empty : (string)a["vs_name"],
        CourseType = !a.Contains("vs_coursetype") ? string.Empty : ((EntityReference)a["vs_coursetype"]).Name,
        CoursePrice = !a.Contains("vs_price") ? -997 : ((Money)a["vs_price"]).Value,
        ProductPrice = !b.Contains("price") ? -996 : ((Money)b["price"]).Value,
        PricelistItemPrice = !c.Contains("amount") ? -995 : ((Money)c["amount"]).Value,
        CurrencySymbol = currencySymbol,
        ActualType = !d.Contains("vs_type") ? -999 : ((OptionSetValue)d["vs_type"]).Value,
        CourseTypeId = (Guid)d["vs_coursetypeid"],
        CourseAreaId = (Guid)e["vs_courseareaid"],
        CourseTypeCode = !d.Contains("vs_code") ? string.Empty : (string)d["vs_code"],
        CourseAreaCode = !e.Contains("vs_code") ? string.Empty : (string)e["vs_code"]
    }
);

// now try and add some filters dynamically
coursesVar = coursesVar.Where(i => i.CourseCode == "X");
coursesVar = coursesVar.Where(i => i.CourseAreaCode == "Y");

var finalList = coursesVar.ToList(); // this line throws the error

【问题讨论】:

  • 不要设置为 IQueryable,设置为 List 并在查询结束时进行强制转换 ToList()
  • 但是它肯定不会作为单个查询执行吗?这将导致返回整个结果集,然后我将随后对整个结果集进行过滤 - 这是我首先尝试通过使用 IQueryable 来避免的。
  • 我认为查询看起来像“from ... where... select new... where... where .. toList()”。 Linq-Crm 非常严格,您只能遵循“从-哪里-选择”的结构。为什么不在第一个查询中添加最后 2 个 where?

标签: linq linq-to-sql crm


【解决方案1】:

不支持是有道理的。否则 linq-2-sql 必须非常聪明,它可以使用额外的过滤器将select new {} 中的整个代码转换为 SQL 并在数据库中执行。这将是一个杀手级功能...

所以你应该在 select new{}

之前添加你的 Where

类似

from a in context.CreateQuery("vs_course")
<and the rest of your complex join>

然后先重做过滤器

// now try and add some filters dynamically
coursesVar = coursesVar.Where(|rephrase in terms of the Original query|}

终于

Select new

这显然有一个缺点,即动态过滤器的“干净”代码需要在原始查询样式中更多地表述。

另一种方法是在添加过滤器之前实现。这将取决于过滤器之前/之后开始返回的行数之间的比率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多