IEnumerable vs IQueryable

时间:2011-01-16 07:28:03

标签: c# linq entity-framework linq-to-entities

我有一个问题:

topics.OrderBy(x => x.Replies.Any() ? x.Replies.OrderBy(y => y.PostedDate).Last().PostedDate : x.PostedDate);

它按上次回复对主题集合进行排序,或者根据自己的发布日期没有回复。它工作得很好并且做得很好。但是,它仅适用于主题类型为IEnumerable<Topic>的情况。如果我试图让它“IQueryable”我得到一个错误,说扩展方法Last()是未知的或者是那种效果。

任何人都知道为什么?出于某种原因,当主题为IQueryable时,在此查询中获取x.Replies.Last()会抛出此异常。

我希望主题是IQueryable,因为我首先从数据库加载包含所有主题的主题,按上次回复排序。然后,我在.skip()和.Take()主题上进行分页。但是,目前它将所有主题都拉入内存,然后对内存中的集合执行.Skip()和.Take()。这是不可接受的,因为添加到论坛的主题越多,加载网站所需的时间就越长,尤其是当数据库没有与网站在同一台计算机上运行时。我需要数据库只返回分页行,而不是所有行。我希望分页在数据库级别进行。

有什么想法吗?

PS - 我正在使用LINQ to Entity with Entity Framework 4.0

4 个答案:

答案 0 :(得分:3)

您是否尝试过topics.OrderBy(x => x.Replies.Any() ? x.Replies.Max(y => y.PostedDate) : x.PostedDate);

答案 1 :(得分:1)

当您尝试运行您发布的代码时,您的数据库上下文是否仍处于活动状态?如果您(或.NET)已经处置了数据库上下文,您将无法再访问IQueryable对象中的数据,因为连接已丢失。

/尤

答案 2 :(得分:1)

IEnumerable:LINQ to Object和LINQ to XML。

IQueryable:LINQ to SQL

答案 3 :(得分:0)

我认为EF无法正确翻译您的查询,它会发生。因为没有必要将每个lamda成功转换为esql,所以它有其自身的局限性。我认为对于你正在寻找的东西来说,这是一个非常复杂的SQL查询。

我建议您可以在名为“LastUpdate”的主题中创建一个新的DateTime字段,该字段将在创建时默认为Topic的PostDate。其次,当您添加新回复时,请确保同时更新Topic的LastUpdate。

通过这样做,您还可以使查询变得非常简单,并且在创建查询时避免不必要的加入。您无需在任何联接中查找回复表的PostDate。

我做这种缓存(在数据库设计术语中称为非规范化),这在设计方面并不完美,但通过性能和编码,它更容易和更简单。