We have a simple LINQ-to-Entities query that should return a specific number of elements from particular page. The example of the request can be:
var query = from r in records
orderby r.createdDate descending
select new MyObject()
{ ... };
//Parameters: pageId = 8, countPerPage = 10
List<MyObject> list = query.Skip(pageId * countPerPage).Take(countPerPage);
The above example works great in most of the cases, but sometimes the list has more than 10 elements. This doesn't seem to be always true and depends from the database data. For example, when we request the page 10 and pass countPerPage as 10, we're getting 10 elements. But when we request the page 12 and pass countPerPage as 10, we're getting 11 elements. Then when we ask for page 21, we're getting 10 elements once again.
Is there any possible reason why that happens?
UPDATE: The query, for sure, is not so simple, as it is in example, and contains the sub-queries.
And here's a more complete example:
var elementsQuery = from m in entityContext.elements
where m.elementSearchText.Contains(filter)
orderby m.CreatedDate descending
select new DataContracts.ElementForWeb()
{
FirstName = m.FirstName,
LastName = m.LastName,
Photos = (from p in m.Photos select p.ID),
PlacesCount = m.Childs.Where(x => x.Place != null).Count() + ((m.MainChild != null)?1:0),
SubElements = (
from t in m.Childs
orderby t.CreatedDate descending
select new DataContracts.ChildForWeb()
{
CommentsCount = t.ChildComments.Count,
Photos = (from p in t.Photos select p.ID),
Comments = (from c in t.ChildComments
orderby c.CreatedDate descending
select new DataContracts.CommentForWeb()
{
CommentId = c.ID,
CommentText = c.CommentText,
CreatedByPhotoId = c.Account.UserPhoto,
CreatedDate = c.CreatedDate,
}).Take(5)
}).Take(5)
};
List<DataContracts.ElementForWeb> elements =
new List<DataContracts.ElementForWeb>(
elementsQuery
.Skip(pageId * countPerPage)
.Take(countPerPage));
UPDATE2: Here's even more interesting test.
for (var i = 0; i < 10; i++) {
Service.GetElementsForWebPaged(12, 10, "",
function (result) {
console.log("Elements returned: " + result.length);
},
function (error) {
});
}
The results are "awesome"!
Elements returned: 11
Elements returned: 11
Elements returned: 10
Elements returned: 11
Elements returned: 11
Elements returned: 10
Elements returned: 11
Elements returned: 10
Elements returned: 11
Elements returned: 11
The Take operator is used to return a given number of elements from an array and the Skip operator skips over a specified number of elements from an array. Skip, skips elements up to a specified position starting from the first element in a sequence.
C# Queryable Take() Method Get specified number of elements from the beginning using the Take() method. The following is our array. int[] marks = { 35, 72, 50, 90, 95, 85, 52, 67 }; Now, use OrderByDescending to order the elements in Descending order. Then use the Take() method to get the elements.
Repeat Method is used to generate a collection of IEnumerable<T> type with a specified number of elements and each element contains same specified value. Second Paramter "int count" represents-> Number of times needed to repeat the generated element of sequnce.
By default, LINQ queries return a list of objects as an anonymous type. You can also specify that a query return a list of a specific type by using the Select clause.
It would be difficult to test this answer because it depends on your schema and test data, etc. But I believe you may be having a problem mixing up IQueryAble results with IEnumerable results.
Remember, an linq-To-Entities query doesn't actually do a roundtrip to the database until a foreach or ToList() is done.
I would suggest first breaking this into pieces:
var elementsQuery = from m in entityContext.elements
where m.elementSearchText.Contains(filter)
orderby m.CreatedDate descending;
var elements = elementsQuery.Skip(pageId * countPerPage).Take(countPerPage)).ToList();
Then build you projection...
var elementsForWeb = from m in elements
select new DataContracts.ElementForWeb()
{
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With