LINQ to Entity Any()与相关的Object Collection

时间:2014-05-09 16:00:08

标签: c# sql linq entity-framework-6

首先,我要说我已经研究过这个问题,并阅读了以下堆栈溢出文章,但没有一篇真正解决这种情况。

情况

我有两个班级

public class Section{
    public string SchoolId{get;set;}
    public string CourseId{get;set;}
    public string SectionId{get;set;}
}

public class RelatedItem{
    public string SchoolId{get;set;}
    public string CourseId{get;set;}
    public string SectionId{get;set;}
    //..
}

我有一个来自一个来源的Section数组,它是一个实际的对象集合。

RelatedItem我通过LINQ to Entities调用DbContext。

我的目标是根据我从其他来源获得的部分获取所有RelatedItem。

我正在编写像这样的查询

Section[] mySections = GetSections();    //Third Party Source
IQueryable<RelatedItem> relatedItems = DbContext.RelatedItems
    .Where(r=>
        mySections.Any(s=> s.SchoolId == r.SchoolId &&
                           s.CourseId == r.CourseId &&
                           s.SectionId == r.SectionId)
    );

问题

在运行时,我收到以下错误

  

无法创建类型的常量值   &#39; ProjectNamespace.Section&#39 ;.只有原始类型或   在此上下文中支持枚举类型。

我找到了一个解决方法,但它涉及到以下操作,但它没有利用我的任何表索引。

var sectionIds = sections.Select(s=>string.Concat(s.SchoolId, "|",s.CourseId, "|",s.SectionId));
IQueryable<RelatedItem> relatedItems = DbContext.RelatedItems
        .Where(r=>
            sectionIds.Contains(string.Concat(r.SchoolId, "|",r.CourseId, "|",r.SectionId))
        );

这段代码有效,而且目前非常快(但这是dev,我的记录数很少)。除了将我的相关项目转换为内存中的集合之外,还有人有任何其他建议吗?

2 个答案:

答案 0 :(得分:2)

请尝试使用Contains

Section[] mySections = GetSections();    //Third Party Source

IQueryable<RelatedItem> relatedItems = DbContext.RelatedItems.Where(r=>
    mySections.Select(s => s.SchoolId).Contains(r.SchoolId) &&
    mySections.Select(s => s.CourseId).Contains(r.CourseId) &&
    mySections.Select(s => s.SectionId).Contains(r.SectionId)
);

Contains应转换为WHERE IN中的SQL条款。

如果使用.NET 3.5和LINQ to Entities,这不会起作用,因为它没有在该版本中实现。

答案 1 :(得分:0)

解决此问题的正确方法是实施IEquitable。以下是有关如何执行此操作的示例Does LINQ to Entities support IEquatable in a 'where' clause predicate?
实现Equals()和GetHashCode()时的一个提示不会调用任何.NET方法(比如getType())只比较原语SchoolId,CourseId,SectionId,它应该转换为表达式树并且工作正常。