C# 新手LINQ问题:在LINQ查询中可以分页吗?

C# 新手LINQ问题:在LINQ查询中可以分页吗?,c#,linq-to-xml,C#,Linq To Xml,是否可以在Linq查询中使用“分页”功能?假设我有一些XML,如下所示: <Root> <BetaSection> <Choices> <SetA> <Choice id="choice1">Choice One</Choice> <Choice id="choice2">Choice Two<

是否可以在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>
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);
}

选择一
选择二
选择三
.
.
.
选择四十八
选择49
选择50
如果我想实现分页功能,我是否能够为LINQ查询提供一个偏移量,这样我就可以从第11个元素开始,到第20个元素结束?如果是这样,如果数据是对象列表而不是XML,那么查询会有什么不同吗

var pagedData = aDataSource.Skip(20).Take(10);
这样,您就跳过了20个元素,并在接下来的10个元素中使用了“Take”和“Skip”扩展方法

myQueryable = myQueryable.Skip(10).Take(10);
现在,如果您需要其中的where子句,它会变得有点棘手:

var q = (from X in Choices
         where x.SomeField == SomeValue
         select X).Skip((page-1)*pageSize).Take(pageSize);
绝对-
Skip()
Take()
实现分页,几乎所有LINQ提供程序都支持

在本例中,看起来您使用的是LINQ to Xml,因此可以忽略以下内容—但对于一般信息:请注意,如果数据通过存储过程来自数据库,则很难在服务器上分页。但是,您可以编写(即页面)“UDF”s。LINQtoSQL支持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"));
}
foreach (var el in doc.SelectNodes(
  "/Root/BetaSection/Choices/SetA/Choice").Cast<XmlElement>()
  .Skip(10).Take(10))
{
    Console.WriteLine(el.GetAttribute("id"));
}

是的。您必须将XML转换为适当的数据源格式,然后MSDN论坛上的这个线程应该提供必要的步骤,让您能够实现它

请查看这些方法和步骤

也可以看到这对分页很有用

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

<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>
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);
}
列表名称=新列表();
names.AddRange(新字符串[]{“John”、“Frank”、“Jeff”、“George”、“Bob”、“Grant”、“McLovin”});
foreach(名称中的字符串名称。第(2,2)页)
{
Console.WriteLine(名称);
}

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);
公共静态IQueryable ToPageOfList(此IQueryable源代码,int pageIndex,int pageSize)
{
返回source.Skip(页面索引*页面大小)。Take(页面大小);
}
//范例
VARG=(从选项中的x选择x).ToPageOfList(1,20);

对于第二种情况,只使用扩展方法可能比混合使用语言语法更容易:var q=Choices.Where(x=>x.SomeField==SomeValue.Skip((page-1)*pageSize.Take(pageSize);在第一种情况下,您可以在中从X中删除
,然后选择X
。在应用orderby时,这是否有效?我的意思是,我希望Linq首先应用orderby,然后跳过并获取……我已经看到了您的代码,但当我们使用xmldoc类加载和读取xml文件时,首先将所有数据加载到内存中。如果所有的数据加载到内存中,从跳过和取函数中选择很少的……它真的被认为是分页吗?分页意味着我将只将少量数据加载到我将要显示或使用的内存中。可以使用linq进行分页。我不知道你想达到什么目的。如果xml文件中保存了大量记录,并且您希望通过linq通过分页从中获取数据,那么这是不可能的。大多数情况下,人们使用xml文档类读取xml文件,然后将完整的xml数据加载到内存中。当全数据加载到内存中时,不应将其视为分页。linq只从内存中读取少量数据并返回……。但这不能称为分页。分页意味着我只将少量数据加载到内存中,我将显示或使用这些数据。