简体   繁体   中英

IEnumerable vs IQueryable

I have a query:

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

It sorts the topics collection by last reply, or if it has no reply then by its own post date. It works great and does its job well. However, it only works if topics is of type IEnumerable<Topic> . If I try to make it `IQueryable' I get an error saying the extension method Last() is unknown or something to that effect.

Anyone know why? For some reason getting x.Replies.Last() within this query while topics is IQueryable throws this exception.

I would like topics to be IQueryable because I first load topics with all topics from the database, sorted by last reply. I then do .Skip() and .Take() on topics for paging. However, currently it is pulling ALL topics into memory and then doing the .Skip() and .Take() on the in-memory collection. This is unacceptable because the more topics that are added to the forum, the longer it takes to load the site, especially when the database is not running on the same computer as the website. I need the database to only return the paged rows, not all rows. I want the paging to occur at the database level.

Any ideas?

PS - I'm using LINQ to Entities with Entity Framework 4.0

Have you tried topics.OrderBy(x => x.Replies.Any() ? x.Replies.Max(y => y.PostedDate) : x.PostedDate); ?

IEnumerable : LINQ to Object and LINQ to XML.

IQueryable : LINQ to SQL

Is you context to the database still active when you try to run the code you posted? If you (or .NET) have disposed the database context you will no longer be able to access the data in the IQueryable object because the connection is lost.

/Viktor

I think EF is unable to translate your query correctly, it happens. Because it is not necessary that every lamda will convert successfully into esql, it has its own limitations. I think it is very complicated SQL query for what you are looking for.

I will suggest you can create a new DateTime field in your topics called "LastUpdate", which will be defaulted to Topic's PostDate when it will be created. Second when you add a new reply, you make sure you update Topic's LastUpdate as well.

By doing this, you also make your query very simple, and you avoid joining unnecessary while creating your query. You don't need to look for PostDate of replies table with any join.

I do this kind of Caching (which is called denormalization in database design terms), this is not perfect in terms of design but by performance and coding, its much easier and simpler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM