LINQ .Take()返回的元素多于请求的元素

我们有一个简单的LINQ-to-Entities查询,它应该从特定页面返回特定数量的元素。 请求的示例可以是:

var query = from r in records orderby r.createdDate descending select new MyObject() { ... }; //Parameters: pageId = 8, countPerPage = 10 List list = query.Skip(pageId * countPerPage).Take(countPerPage); 

上面的示例在大多数情况下都很有效,但有时候列表中有10个以上的元素。 这似乎并不总是正确的,取决于数据库数据。 例如,当我们请求页面10并将countPerPage传递为10时,我们得到10个元素。 但是当我们请求页面12并将countPerPage作为10时,我们得到了11个元素。 然后,当我们要求第21页时,我们再次获得10个元素。

这有什么可能的原因吗?

更新:查询,当然,并不像在示例中那么简单,并包含子查询。

这是一个更完整的例子:

 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 elements = new List( elementsQuery .Skip(pageId * countPerPage) .Take(countPerPage)); 

更新2 :这是更有趣的测试。

  for (var i = 0; i < 10; i++) { Service.GetElementsForWebPaged(12, 10, "", function (result) { console.log("Elements returned: " + result.length); }, function (error) { }); } 

结果是“真棒”!

 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 

测试这个答案很难,因为它取决于你的架构和测试数据等。但我相信你可能在将IQueryAble结果与IEnumerable结果混合时遇到问题。

请记住,在完成foreach或ToList()之前,linq-To-Entities查询实际上不会对数据库进行往返。

我建议先把它分成几块:

 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(); 

然后建立你投射…

 var elementsForWeb = from m in elements select new DataContracts.ElementForWeb() { ... }