【问题标题】:Entity Framework Paging实体框架分页
【发布时间】:2016-05-04 22:30:59
【问题描述】:

我一直在寻找代码,如果我可以在 EF 中对大数据进行分页,例如从 1 到 100... 或更多,那么 Web 应用程序真的很慢。 我这里有代码,但我还没有找到解决方案。

我真的需要在页面中制作数据或加快数据查看速度 记录多于(1,5000,000)条记录。 如果有人有任何 EF 分页的代码或解决方案,或者数据可以更快地回复我,请各位。

谢谢你们,

[代码]

var openComplaintsAssignedToOffice = individual.Office.AssignedComplaints
                                                      .ToArray()
                                                      .Where(n => n.Individuals.Any(e => e.Employed))
                                                      .ToArray() ; 

if (!complaintModel.ShowClosedComplaints)
{
    openComplaintsAssignedToOffice = openComplaintsAssignedToOffice.Where(c => c.CurrentStatus != ComplaintStatus.Closed)
                                                                   .ToArray();
}

complaintModel.OpenComplaintsAssignedToMyOffice = openComplaintsAssignedToOffice.OrderByDescending(c => c.UpdatedDateTime)
                                                                                .ToArray();
complaintModel.OpenComplaintsAssignedToMyOffice = openComplaintsAssignedToOffice.OrderByDescending(c => c.UpdatedDateTime)
                                                                                .ToArray();
return complaintModel;

【问题讨论】:

  • 您只是在寻找.Skip() 和.Take() 函数吗?
  • 您提出了一个非常琐碎的问题,并附有似乎与之无关的代码。或者,更准确地说,代码本身似乎会导致问题。

标签: asp.net-mvc webforms entity-framework-4


【解决方案1】:

您没有具体说明要在哪里分页您的数据,所以为了简单起见,我假设它在这里:

individual.Office.AssignedComplaints

(不过,作为旁注,您似乎很随意地到处乱扔.ToArray()。请理解,这可能会通过强制系统加载而严重影响性能许多记录在对那些本可以在数据源本身上执行的记录执行过滤之前进入内存。)

您可以使用.Skip() 和.Take() 函数有效地对结果进行分页。例如,假设您有以下值:

var pageSize = 10;
var currentPage = 3;  // 0-indexed, of course

考虑到这些,您应该会看到记录 30-39,对吗?因此,您将使用这些值来分页数据:

individual.Office.AssignedComplaints.Skip(pageSize * currentPage).Take(pageSize)

这将导致跳过前 30 条记录 (0-29) 并获取接下来的 10 条记录,而忽略其余记录。有效地返回总结果集的“第 3 页”。

此分页可应用于整个表达式树中可以过滤结果集的任何位置。在排序之前或之后,在 .Where() 子句之前或之后等。根据您打算如何塑造和呈现数据,它在逻辑上属于什么位置取决于您。

【讨论】:

    【解决方案2】:

    通常,您将使用Skip() 和Take() 方法来处理分页数据。 Skip() 将确定要“跳过”多少元素来定义页面的起点,Take() 将确定要抓取多少元素。

    // This will skip the first 10 records and take the next 20
    var page = data.Skip(10).Take(20);
    

    考虑Deferred Execution

    处理此问题时要考虑的一件非常重要的事情是,您希望尽可能地推迟执行。 ToList() 或 ToArray() 之类的方法实际上会将您的值存储在内存中,这是您希望避免的,尤其是对于大型数据集。

    如果您可以避免调用此类方法,您将确保查询本身只执行一次(因此只返回一页记录而不是整个数据集,然后在内存中分页)。

    您可能会重构代码以使用分页,如下所示:

    // Define your page size and initial page
    var page = 0;
    var pageSize = 20;
    // Get any open complaints
    var openComplaints = individual.Office.AssignedComplaints.Where(n => n.Individuals.Any(e => e.Employed));
    // Determine if complaints should be shown
    if (!complaintModel.ShowClosedComplaints)
    {
         openComplaints = openComplaints.Where(c => c.CurrentStatus != ComplaintStatus.Closed);                                                            
    }
    // Finally order and page your data
    return openComplaints.OrderByDescending(c => c.UpdatedDateTime)
                         .Skip(page * pageSize)
                         .Take(pageSize)
                         .ToArray();
    

    【讨论】:

    • 我要感谢 Rion 的代码,如果我变成这样的个人,它实际上是有效的。Office.AssignedComplaints.Skip(pageSize * currentPage).Take(pageSize)
    猜你喜欢
    • 2012-04-26
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多