LINQ to SQL分页

时间:2009-04-23 12:52:28

标签: sql linq-to-sql paging

我一直在使用LINQ To SQL的.Skip()和.Take()扩展方法一段时间没有问题,但在我使用它们的所有情况下,它总是用于单个表 - 如:

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

我的问题是我现在正在从多个表中投射一组结果,并且我希望在整个集合上进行分页(并且仍然可以获得在数据库中分页的好处)。

我的实体模型如下所示:

广告系列[包含多个]群组,群组[有多个]联系人

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

广告系列 - > CampaignToGroupMapping - >组 - > GroupToContactMapping - >接触

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

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

我曾尝试使用.SelectMany编写一个LINQ查询,将每组中的联系人集合投影到一个线性数据集中,希望我可以.Skip()。从中获取(。)

我的尝试是:

 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用于参数 totalRequired (传递给.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 个答案:

答案 0 :(得分:4)

要模仿您提供的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()

您是否尝试翻页广告系列,收件人或两者兼而有之?

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我认为你的尝试非常接近;也许我错过了一些东西,但我认为你只需要在Skip / Take之前关闭你的SelectMany():

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

注意:在“/ * Contact Data * /}”之后添加“)”并从“之后”删除“)”。获取(totalRequired)“