【问题标题】:Can I shape a LINQ query by modifying the IQueryable?我可以通过修改 IQueryable 来塑造 LINQ 查询吗?
【发布时间】:2017-08-04 11:33:24
【问题描述】:

我有一个大型 LINQ 查询,导致 SQL 查询效率低下。我很确定我可以通过调整查询对其进行很多优化(就像 Scott Gu 在 this blog post 中提到的,以及 Eugene Prystupa 在 this excellent blog post 中提到的那样,他称之为“提示”)。

但是,此查询是重要的遗留代码,因此我宁愿不触及查询本身。是否可以通过修改生成的 IQueryable 来塑造 LINQ 查询?

例如,假设低效查询在GetOrders 中,它以IQueryable<Order> 形式返回查询结果。我可以塑造 IQueryable 结果吗?例如:

var result = GetOrders();

result = result.Select(o =>
    new { o, o.Id, o.Customer, o.Payment })
    .AsEnumerable()
    .Select(o => o.o);

注意最后的Select,即取回Order对象。 (有关此 gem,请参阅 Prystupa's blog。)此示例塑造的重点是让 LINQ2SQL(或实体框架)将 Order 表与 Customer 和 Payment 连接起来。原始查询将在查询 Order 后查询这些表 n 次,其中 n 是 Orders 的数量。

【问题讨论】:

  • 能否先提供GetOrders() 函数,因为我认为它不会返回 IQuerable?
  • 为什么不呢?它返回表上Where 的结果。即,return Db.Orders.Where(o => … 等。
  • GetOrders的返回类型是IQueryable还是IEnumerable?
  • IQueryable。为什么你认为不是?
  • @Protectorone:如果该方法返回 IQueryable,则还没有转换为 sql。然后,您几乎可以做任何您想做的事情。但是你的问题有点奇怪,你只问“有没有可能……”,答案是“是的”。那么你真正期待什么样的建议呢?

标签: c# sql .net linq linq-to-sql


【解决方案1】:

通过实验,我发现这确实是可能的。只要查询仍然是 LINQ-to-SQL 或 LINQ-to-Entities 而不是 LINQ-to-Objects,您仍然可以调整查询。 (当您通过调用 ToListAsEnumerable 之类的方法将结果集放入内存时,查询将变为 LINQ-to-Objects。)

但有一个很大的警告:您只能在一对一的关系子级上获得 SQL 连接。如果您在Select 的匿名对象中包含一对多或多对多的子对象,则生成的SQL 仍然会有n 对子表的附加查询,其中n 是数字的记录。这让我绊倒了很长时间,让我觉得塑形根本没有做任何事情。

不过,我仍然希望我能找到关于这件事的官方文件。

【讨论】:

    【解决方案2】:

    我相信,正如博客文章所指出的,你必须做一个AsEnumerable 否则中间选择将被优化出查询:

    var result = GetOrders();
    
    result = result.Select(o => new { o, o.Id, o.Customer, o.Payment })
                   .AsEnumerable()
                   .Select(o => o.o);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-10
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-03
      相关资源
      最近更新 更多