如何构造 LINQ (EF) 查询以投影数据页

本文关键字:投影 数据 查询 何构造 LINQ EF | 更新日期: 2023-09-27 18:36:53

我熟悉 LINQ 的大部分功能,但似乎无法弄清楚如何在单个 LINQ 查询中返回多页数据的投影。

这是场景...我正在构建一个"邮件合并",其中每个字母包含一个表,但该表仅限于 40 行信息。因此,如果特定收件人的表格信息包含 100 行,我希望返回三个投影对象;一个用于前 40 行(包括收件人),一个用于后 40 行,同样包括同一收件人,另一个用于具有相同收件人的最后 20 行。

Recipient A: Table Rows: 50
Recipient B: Table Rows: 100
Recipient C: Table Rows: 20
The iteration results that I want are:
{
    Recipient: A,
    Table: (rows 0-39)
},
{
    Recipient: A,
    Table: (rows 40-49)
},
{
    Recipient: B,
    Table: (rows 0-39)
},
{
    Recipient: B,
    Table: (rows 40-79)
},
{
    Recipient: B,
    Table: (rows 80-99)
},
{
    Recipient: C,
    Table: (rows 0-19)
}

提前感谢您提供的任何帮助或指向您可能能够提供的其他信息来源的指示。

如何构造 LINQ (EF) 查询以投影数据页

在建议更好的替代方案之前,您可以使用以下内容。

var q = db.Recipients;
// this loads all table rows...
// so you should filter q as per 
// needed rowset only
        var listq = q
           .SelectMany(x => 
               x.Table.Select( (y,i)=> new {
                  Key = y.RecipientID + "-" + ((int)i/(int)40),
                  Value = y
               })
           );
        var model = listq.GroupBy(x=>x.Key)
           .Select( x=> new {
               Recipient = x.Select(y=>y.Value.Recipient).First(),
               Table = x.Select(y=>y.Value)
           });
  1. 第一步,我们将从数据库中获取具有表导航属性的所有记录。
  2. 接下来,我们将调用 SelectMany,它将扁平化层次结构,但是,我们将创建一个新键,其中包含 RecipientID 和索引除以 40,因此第一个收件人是 1,索引是 1,所以键将是 1-0,依此类推对于 41 的第一个索引,键将是 1-1。
  3. 然后我们将按新创建的密钥分组,
  4. 然后我们将通过选择第一个收件人和枚举表中的其余部分来选择收件人和表。

完整的工作示例在这里..

    public class Recipient
    {
        public Recipient()
        {
            Table = new List<Table>();
        }
        public long RecipientID { get; set; }
        public List<Table> Table { get; set; }
    }
    public class Table
    {
        public long TableID { get; set; }
        public long RecipientID { get; set; }
        public Recipient Recipient { get; set; }
    }
    private static void Add(List<Recipient> list, long index, int p2)
    {
        Recipient r = new Recipient
        {
            RecipientID = index
        };
        for (int i = 0; i < p2; i++)
        {
            Table t = new Table
            {
                TableID = i,
                Recipient = r,
                RecipientID = r.RecipientID
            };
            r.Table.Add(t);
        }
        list.Add(r);
    }
    static void Main(string[] args)
    {
        List<Recipient> list = new List<Recipient>();
        Add(list, 1, 80);
        Add(list, 2, 15);
        Add(list, 3, 99);
        var listq = list
           .SelectMany(x => 
               x.Table.Select( (y,i)=> new {
                  Key = y.RecipientID + "-" + ((int)i/(int)40),
                  Value = y
               })
           );
        var model = listq.GroupBy(x=>x.Key)
           .Select( x=> new {
               Recipient = x.Select(y=>y.Value.Recipient).First(),
               Table = x.Select(y=>y.Value)
           });

        foreach (var item in model)
        {
            Console.WriteLine("{0}={1}",item.Recipient.RecipientID,item.Table.Count());
        }
        Console.ReadLine();
    }