【问题标题】:Newbie LINQ Question: Is Paging in LINQ Queries Possible?新手 LINQ 问题:LINQ 查询中是否可以分页?
【发布时间】:2008-12-08 20:42:08
【问题描述】:

是否可以在 Linq 查询中使用“分页”功能?假设我有一些这样的 XML:

<Root>
    <BetaSection>
        <Choices>
            <SetA>
                <Choice id="choice1">Choice One</Choice> 
                <Choice id="choice2">Choice Two</Choice>
                <Choice id="choice3">Choice Three</Choice>
                .
                .
                .
                <Choice id="choice48">Choice Forty-Eight</Choice>
                <Choice id="choice49">Choice Forty-Nine</Choice>
                <Choice id="choice50">Choice Fifty</Choice>
            </SetA>
        </Choices>
    </BetaSection>
</Root>

如果我想实现分页功能,是否可以为 LINQ 查询提供偏移量,以便我可以从第 11 个元素开始并在第 20 个元素结束?如果是这样,如果数据是对象列表而不是 XML,那么查询会有什么不同吗?

【问题讨论】:

  • 可以通过 linq 进行分页。我不知道你想达到什么目的。如果在 xml 文件中保存了大量记录,并且您想通过 linq 使用分页从那里获取数据,那么这是不可能的。大多数时候人们使用 xml doc 类来读取 xml 文件,然后将完整的 xml 数据加载到内存中。当完整数据加载到内存中时,不应将其视为分页。 linq 只会从内存中读取少量数据并返回........但这不能说是分页。分页意味着我只会将少量数据加载到我要显示或使用的内存中。

标签: c# linq-to-xml


【解决方案1】:
var q = from X in Choices.Skip((page-1)*pageSize).Take(pageSize)
        select X;

现在,如果你需要一个 where 子句,那就有点棘手了:

var q = (from X in Choices
         where x.SomeField == SomeValue
         select X).Skip((page-1)*pageSize).Take(pageSize);

【讨论】:

  • 对于第二种情况,使用扩展方法可能更容易,而不是混合语言语法: var q = Choices.Where( x => x.SomeField == SomeValue ).Skip( (page - 1) * pageSize ).Take( pageSize );
  • 第一种情况你可以删除from X inselect X
  • 申请orderby的时候会这样吗?我的意思是我希望 Linq 先申请 orderby 然后跳过并采取...
【解决方案2】:

看看Queryable.SkipQueryable.Take 方法。

另请参阅这个有用的extension methods 进行分页,

使用这些方法,您可以这样做:

List<string> names = new List<string>();
names.AddRange(new string[]{"John","Frank","Jeff","George","Bob","Grant", "McLovin"});

foreach (string name in names.Page(2, 2))
{
    Console.WriteLine(name);
}

【讨论】:

    【解决方案3】:

    绝对 - Skip()Take() 实现分页,并且几乎所有 LINQ 提供程序都支持。

    在这种情况下,您似乎正在使用 LINQ-to-Xml,因此请随意忽略以下内容 - 但对于一般信息:请注意,如果数据通过存储过程来自数据库,则很难在服务器上寻呼。但是,您可以编写(即页面)“UDF”。 LINQ-to-SQL 支持 UDF(通过 [FunctionAttribute]),但不支持实体框架。如果您使用的是自动生成的数据库查询,这不是问题。

    请注意,使用 xml,您还可以使用 xpath 做很多事情 - 这里使用 XmlDocument

    foreach (XmlElement el in doc.SelectNodes(
      "/Root/BetaSection/Choices/SetA/Choice[position() > 11 and position() < 20]"))
    {
        Console.WriteLine(el.GetAttribute("id"));
    }
    

    或者Skip()/Take()(仍然是XmlDocument):

    foreach (var el in doc.SelectNodes(
      "/Root/BetaSection/Choices/SetA/Choice").Cast<XmlElement>()
      .Skip(10).Take(10))
    {
        Console.WriteLine(el.GetAttribute("id"));
    }
    

    【讨论】:

    • 我看过你的代码,但是当我们使用 xmldoc 类加载和读取 xml 文件时,首先将所有数据加载到内存中。如果所有数据都加载到内存中并使用skip&take功能从那里选择一些......它真的认为是分页吗?分页意味着我只会将少量数据加载到我要显示或使用的内存中。
    【解决方案4】:

    James Curran 说得对,您可以通过创建一个扩展方法以供以后重用来简化它。

    您还可以修改代码以返回一个对象,该对象可以根据 pageSize 和 pageIndex 跟踪列表中有多少项目以及应该有多少页。

    public static IQueryable<T> ToPageOfList<T>(this IQueryable<T> source, int pageIndex, int pageSize)
    {
        return source.Skip(pageIndex * pageSize).Take(pageSize);
    }
    
    //Example
    var g = (from x in choices select x).ToPageOfList(1, 20);
    

    【讨论】:

      【解决方案5】:
      var pagedData = aDataSource.Skip(20).Take(10);
      

      这样,您将跳过 20 个元素并获取接下来的 10 个元素

      【讨论】:

        【解决方案6】:

        “Take”和“Skip”扩展方法提供了这一点。

        myQueryable = myQueryable.Skip(10).Take(10);
        

        【讨论】:

          【解决方案7】:

          是的。您必须将 XML 转换为正确的 DataSource 格式,然后 MSDN 论坛上的这个帖子应该提供必要的步骤,让您能够了解如何实现它...

          MSDN - LINQ with pagination

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多