【问题标题】:LINQ To SQL PagingLINQ To SQL 分页
【发布时间】:2009-04-23 12:52:28
【问题描述】:

我已经在 LINQ To SQL 中使用 .Skip() 和 .Take() 扩展方法一段时间了,没有任何问题,但在我使用它们的所有情况下,它始终是针对单个表的 -如:

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

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

我的实体模型如下所示:

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

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

Campaign -> CampaignToGroupMapping -> Group -> GroupToContactMapping -> Contact

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

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

我曾尝试使用 .SelectMany 编写一个 LINQ 查询,将每个组中的一组联系人投影到一个线性数据集中,希望我可以从中使用 .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())发生在每个组,而不是整个数据集。

这意味着如果我为参数 totalRequired 使用值 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 语法来实现这一点?

【问题讨论】:

    标签: sql linq-to-sql paging


    【解决方案1】:

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

    您是在尝试对活动、收件人或两者都进行分页吗?

    【讨论】:

    • 我相信您需要先订购才能使用 Skip and Take。对我来说就是这样。
    【解决方案2】:

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

    【讨论】:

    • 理想情况下,我正在寻找仅使用 LINQ To SQL 的解决方案。就像我在回答中提到的那样,我也可以直接从 ADO.NET 执行 SQL 查询——但我想使用 LINQ To SQL 来与其他代码保持一致。感谢您的建议。
    • LINQ to SQL 支持视图。只需将它们拖放到设计器中即可。我知道您需要一个 LINQ to SQL 解决方案。我建议您创建一个供 LINQ to SQL 框架使用的视图。
    【解决方案3】:

    我认为您的尝试非常接近;也许我错过了一些东西,但我认为你只需要在 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 */ })”之后添加“)”并从“.Take(totalRequired)”之后删除“)”

    【讨论】:

      猜你喜欢
      • 2017-06-07
      • 2015-11-03
      • 2010-10-22
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多