【问题标题】:how to implement Linq to Entities IQueryable TakeWhile() functionality如何实现 Linq to Entities IQueryable TakeWhile() 功能
【发布时间】:2013-06-17 10:28:43
【问题描述】:

今天在使用 LINQ 时,我发现 LINQ to 实体不支持 TakeWhile(),是否有任何有效的方法来实现这样的功能?我的用例如下 -

我有一个 Employee 实体,并且我已经按名称对实体进行了排序,现在我想从这个 IQueryable 中获取记录直到时间 (EmployeeID = 123)

类似的东西 -

IQueryable<Employee> employees = ObjectContext.Employees
          .OrderBy(a => a.Name)
          .TakeWhile(a => a.EmployeeId != 123)

但是在上面的代码中,Linq to Entities 不支持 TakeWhile,因此它会引发错误。


我正在尝试以下方法,如果有人有更好更有效的方法,请告诉我:

  • 获取前 X 条记录,
  • 检查所需的 EmployeeId 是否是其中的一部分,
    • 如果没有,则获取下一组 X 记录
    • 并将它们与上一组连接
    • 并再次检查 EmployeeID 是否是其中的一部分,
    • 当在 X 记录集中找到匹配的 EmployeeId 时中断循环。

【问题讨论】:

  • 这个查询是什么意思?应该是.Where(a =&gt; a.Id &lt; 123)
  • 你为什么按名字点单,却按身份证号?
  • 实际上我正在编写一种延迟加载逻辑,在注销和登录后加载列表时,我想加载项目的数量,直到从列表中选择项目的位置和其余部分将作为延迟加载的一部分检索的项目...
  • 如果您在OrderBy 之后附加.AsEnumerable(),它将起作用,但在代码中而不是DB 中执行TakeWhile
  • hmmm.. 但在这种情况下,它会从员工表中获取所有记录.. 还有其他更有效的方法吗?

标签: c# linq linq-to-entities


【解决方案1】:

您不应按Name 排序,而应存储在Id 的某个位置。可能,这会有所帮助:

// eager loading of employees, which name is less or equal, than stored name:
ObjectContext.Employees.Where(a => a.Name.CompareTo(storedName) < 0 || a.Name.CompareTo(storedName) == 0)

// lazy loading the rest of employees:
ObjectContext.Employees.Where(a => a.Name.CompareTo(storedName) > 0)

【讨论】:

    【解决方案2】:

    SQL 中没有 TakeWhile() 等效项,因此您必须在内存中执行该步骤。在添加没有 SQL 等效项的过滤器之前,您可以通过将 IQueryable&lt;&gt; 强制转换为 IEnumerable&lt;&gt; 来强制执行 SQL。

    var employees = ObjectContext.Employees
          .OrderBy(a => a.Name)
          .AsEnumerable()  // filters after this point will be done in memory on each record
          .TakeWhile(a => a.EmployeeId != 123)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2015-08-14
      • 2011-06-10
      • 1970-01-01
      相关资源
      最近更新 更多