LINQ。取()返回比请求更多的元素 [英] LINQ .Take() returns more elements than requested

查看:265
本文介绍了LINQ。取()返回比请求更多的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个简单的LINQ到实体查询应返回从特定页面元素的特定号码。
请求的例子可以是:



  VAR的查询=从记录
排序依据R R。 createdDate降
选择新MyObject来()
{...};

//参数:PAGEID = 8,countPerPage = 10
名单,LT;为MyObject>清单= query.Skip(PAGEID * countPerPage)。取(countPerPage);



上面的例子在大多数情况下的伟大工程,但有时列表中有超过10个元素。这似乎并不总是正确,并从数据库中的数据依赖。
为例,当我们要求第10页,并通过countPerPage为10,我们正在10个元素。但是,当我们要求第12页,并通过countPerPage为10,我们正在11个元素。然后,当我们问了21页,我们再次获得10个元素。



是否有任何可能的原因出现这种情况?



更新:
查询,可以肯定,不是那么简单,因为它是例子,并且包含子查询



这是一个更完整的例子:

  VAR elementsQuery =从米entityContext.elements 
,其中m.elementSearchText。包含(过滤器)
排序依据m.CreatedDate降
选择新DataContracts.ElementForWeb()
{
名字= m.FirstName,
姓氏= m.LastName,
=照片(从对在m.Photos选择p.ID),
PlacesCount = m.Childs.Where(X =>!x.Place = NULL).Count之间的()+((M。 MainChild = NULL)1:?0),
子元素=($ b $从T b在m.Childs
排序依据t.CreatedDate降
选择新DataContracts.ChildForWeb()
{
CommentsCount = t.ChildComments.Count,
照片=(上接第在t.Photos选择p.ID),
评论=(从C在t.ChildComments
排序依据c.CreatedDate降
选择新DataContracts.CommentForWeb()
{
CommentId = c.ID,
CommentText = c.CommentText,
CreatedByPhotoId = C。 。Account.UserPhoto,
CreatedDate = c.CreatedDate,
})采取(5)
})采取(5)
}。

名单,LT; D​​ataContracts.ElementForWeb>元素=
新的List< D​​ataContracts.ElementForWeb>(
elementsQuery
.Skip(PAGEID * countPerPage)
。取(countPerPage));



UPDATE2 :这里有更有趣的测试



 为(VAR I = 0;我小于10;我++){$​​ b $ b Service.GetElementsForWebPaged(12,10,,
功能(结果){
的console.log(元素返回:+ result.length);
},
功能(错误){
});
}



的结果是真棒!

 元素返回:11 
元素返回:11
元素返回:10
元素返回:11
元素返回: 11
元素返回:10
元素返回:11
元素返回:10
元素返回:11
元素返回:11


解决方案

这将是很难测试这个答案,因为它取决于你的架构和测试数据,等等。
但是我相信你可能有一个问题,混合了IEnumerable的结果IQueryable的结果。



记住,一个LINQ到实体查询实际上并不做,往返于数据库中,直到一个foreach或了ToList()完成



我会建议先破成碎片这样的:

  VAR elementsQuery =从entityContext.elements 
m其中m.elementSearchText.Contains(过滤器)
排序依据m.CreatedDate下降;

VAR元素= elementsQuery.Skip(PAGEID * countPerPage)。取(countPerPage))了ToList()。



然后建立你的投影......

  VAR elementsForWeb =从米元素
选择新DataContracts.ElementForWeb()
{

}


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

解决方案

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()
                     {
                     ...
                     }

这篇关于LINQ。取()返回比请求更多的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆