ncook wrote:
Actually it turns out that approach doesn't work unfortunately. I need the entities to be in the same order as the original query in the stored procedure (ordered by an count(*) aggregate). I tried using context and adding the collection to the context before (re)fetching the collection, but it creates duplicate rows by appending the enties to the collection for some reason instead of updating them.
That last problem is fixed in the build that will be released tomorrow (saturday). At least it looks like the problem you ran into, it might not be the same. The core is that a collection has a flag: DoNotPerformAddIfPresent. This flag is set to false by default, so an Add will always add the same entity again. Setting that flag to true will prevent the add from adding the same entity again. A context will make sure the fields are updated, so the fields are updated, but you now get dupes, and you don't want that. This only happens with prefetch path + entitycollection + context used together in a fetch.
The query you're using is actually not that efficient, though it's more efficient than a subquery in the select list.
The main problem is that you're retrieving the # of views dynamically, each time the data is requested. You shouldn't do that. When the data is viewed, do a direct update on a count field in the content entity in the db, so that the field is increased with 1. You then just have to fetch the data when you're reading the content.
This forum uses the same approach. The # of posts you see under the user and the # of posts in the threads aren't retrieved dynamically, they're increased when the data changes. This means that the fetches are much faster, which is what you want because the data is often way more read than written.
I could rewrite the query you posted, by adding a ScalarQueryExpression to the selectlist in a dynamic list which would perform the count(*) for the # of views of the contentitem, however that's less efficient than doing a join with a select like you're doing now.