代码之家  ›  专栏  ›  技术社区  ›  Martin

LINQ到SQL分页

  •  9
  • Martin  · 技术社区  · 15 年前

    我使用.Skip()和.Take()扩展方法和LINQ To SQL已经有一段时间了,现在没有问题,但是在所有情况下,我都使用它们来处理单个表,例如:

    database.Users.Select(c => c).Skip(10).Take(10);
    

    我的问题是,我现在正在从多个表中投影一组结果,我想对整个结果集进行分页(仍然可以从数据库中获得分页的好处)。

    我的实体模型如下:

    一个活动[有许多]组,一个组[有许多]联系人

    这是通过数据库中的关系建模的,如

    活动->活动组映射->组->组ToContactMapping->联系人

    我需要生成一个包含活动详细信息的数据结构,以及通过CampaignToGroupMapping与活动关联的每个联系人的列表,即。

    Campaign
       CampaignName
       CampaignFrom
       CampaignDate
       Recipients
          Recipient 1
          Recipient 2
          Recipient n...
    

    我试着用.SelectMany将每组联系人的集合投影到一个线性数据集中,希望能从中得到.Skip().Take()。

    我的尝试是:

     var schedule = (from c in database.Campaigns
                     where c.ID == highestPriority.CampaignID
                     select new PieceOfCampaignSchedule
                     {
                         ID = c.ID,
                         UserID = c.UserID,
                         Name = c.Name,
                         Recipients = c.CampaignGroupsMappings.SelectMany(d => d.ContactGroup.ContactGroupMappings.Select(e => new ContactData() { /*Contact Data*/ }).Skip(c.TotalSent).Take(totalRequired)).ToList()
    
                     }).SingleOrDefault();
    

    问题是分页(关于Skip()和Take())是针对每个组而不是整个数据集进行的。

    这意味着如果我使用值200作为参数 所需总数 (传递到.Take())并且我有3个组与此活动关联,将从每个组中获取200,而不是从与此活动关联的每个组的总数据中获取200。

    在SQL中,我可以通过以下查询来实现:

    select * from
    (
        select [t1].EmailAddress, ROW_NUMBER() over(order by CampaignID desc) as [RowNumber] from contacts as [t1]
        inner join contactgroupmapping as [t2] on [t1].ID = [t2].ContactID
        inner join campaigngroupsmapping as [t3] on [t3].ContactGroupID = [t2].GroupID
        where [t3].CampaignID = @HighestPriorityCampaignID
    
    ) as [Results] where [Results].[RowNumber] between 500 and 3000
    

    有了这个查询,我将翻阅与特定活动相关联的每个组的联系人组合集。所以我的问题是,如何使用LINQ To SQL语法来实现这一点?

    3 回复  |  直到 15 年前
        1
  •  4
  •   Jimmie R. Houts    12 年前

    要模拟您提供的SQL查询,请执行以下操作:

    var schedule = (from t1 in contacts
                    join t2 in contactgroupmapping on t1.ID equals t2.GroupID
                    join t3 in campaigngroupsmapping on t3.ContactGroupID = t2.GroupID
                    where t3.CampaignID = highestPriority.CampaignID
                    select new PieceOfCampaignSchedule
                    {
                      Email = t1.EmailAddress
                    }).Skip(500).Take(2500).ToList()
    

    你是想翻阅活动、收件人,还是两者都翻阅?

        2
  •  0
  •   rguerreiro    15 年前

    使用视图聚合来自多个表的结果,然后在视图上使用LINQ

        3
  •  0
  •   Chris Shaffer    15 年前

    我认为您的尝试非常接近;也许我遗漏了一些内容,但我认为您只需要在跳过/接受之前关闭SelectMany():

    Recipients = c.CampaignGroupsMappings.SelectMany(d => d.ContactGroup.ContactGroupMappings.Select(e => new ContactData() { /*Contact Data*/ })).Skip(c.TotalSent).Take(totalRequired).ToList()
    

    注意:在“/*联系人数据*/}”后添加“)”并从“.Take(totalRequired)”后删除“)”