首先,我要说我已经研究过这个问题,并阅读了以下堆栈溢出文章,但没有一篇真正解决这种情况。
我有两个班级
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,我的记录数很少)。除了将我的相关项目转换为内存中的集合之外,还有人有任何其他建议吗?
答案 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,它应该转换为表达式树并且工作正常。