【发布时间】:2012-06-16 15:50:18
【问题描述】:
以下 linq2entities 代码似乎调用了 FirstOrDefault 扩展的 IEnumerable 版本,因为 PersonHistories 是一个 ICollection。然而,在运行时,它实际上调用了 IQueryable 版本。
var test = db.Persons.Where(d => d.PersonKey == 4)
.Select(f => f.PersonHistories.FirstOrDefault());
我遇到的问题是我使用的自定义查询提供程序不执行此自动转换,并且我收到错误“...ICollection 不能用于 IQueryable 类型的参数”。因此需要显式调用 AsQueryable 来解决这个问题,但对于复杂的查询,它会变得非常多余并且感觉不是很干燥:
db.Persons.Where(d => d.PersonKey == 4)
.Select(f => f.PersonHistories.AsQueryable().FirstOrDefault());
我在框架参考源中四处寻找试图找到 Linq 2 实体访问者/提供者的东西,但没有运气(也许不是任何开放参考源的一部分)。 基础提供者如何实现对 AsQueryable 的隐式使用?
我明白这些被翻译成表达式树。 我确实了解 Enumerable.FirstOrDefault 被提供商替换为 Queryable.FirstOrDefault 。这是问题的前提。
【问题讨论】:
-
尝试翻转它,看看它“正常工作”:
db.Persons.Where(d => d.PersonKey == 4).PersonHistories.FirstOrDefault() -
不,不起作用,因为 .Where 返回一个集合/IQueryable,其中没有这样的 PersonHistories 字段。您必须使用 SingleOrDefault 之类的东西来获取单个项目,或者使用 .Select 来投影嵌套字段。我选择使用嵌套投影来演示这个问题,因为这是我遇到问题的地方。由于 db.Persons 是一个 DbSet,因此它是 IQueryable,因此 .Where 自动是 IQueryable 版本,但相比之下,Person.PersonHistories 是作为 ICollection 实现的,处理起来更具挑战性。
标签: c# linq entity-framework linq-to-entities