【问题标题】:Entity Framework Core Linq query to filter related entityEntity Framework Core Linq 查询过滤相关实体
【发布时间】:2018-06-01 03:45:02
【问题描述】:

我一直在研究如何在使用 Include 时编写关于通过 Entity Framework Core 过滤相关实体的查询,假设我有以下两个类:

public class Order
{
  public int OrderId {get; set;}
  public String CreatedBy{get; set;}
  public virtual Collection<OrderDetail> OrderDetails { get; set; } = new Collection<OrderDetail>();
}

public class OrderDetail
{
   public Int64? OrderDetailID { get; set; }
   public Int64? OrderID { get; set; }
   public string ProductName { get; set; }
}

如果我想查找由“Jason”创建的所有订单,并且哪个订单详细信息的产品名称等于“Apple”,在 sql 中会是这样的: 隐藏复制代码

SELECT *
FROM Orders O
INNER JOIN OrderDetail OD ON O.OrderId = OD.OrderId
WHERE O.CreationUser = 'Jason' and OD.ProductName = 'Apple'

但是我无法弄清楚如何使用 EntityFramework 来编写它,如下所示的内容不起作用:

 await DbContext.Set<Order>()
    .Include(p => p.OrderDetails)
    .Where(o => o.CreationUser == "Jason")
    .Where(o => o.OrderDetails.Where(od => od.ProductName == "Apple"));

有像上面这样的场景,我知道如何使用上面示例中的 Order 等基实体类过滤属性,但我不知道如何使用 Include/ThenInclude 处理相关实体,例如对 OrderDetail.ProductName 进行过滤, 我已经研究了很多,但仍然没有任何线索,因此最后我不得不使用 Store 程序来代替,大​​多数开发人员不建议这样做。

也许 linq sql 可以做到这一点?

请帮助我更多地了解它!非常感谢所有可以分享您的知识的人!

【问题讨论】:

  • something like below would not work:具体是什么不起作用?

标签: c# entity-framework-core


【解决方案1】:

您可以简单地将您的 SQL 脚本转换为 linq:

var orders = (from O in context.Order
              join OD in context.OrderDetail on O.OrderId equals OD.OrderId
              where O.CreatedBy == "Jason" && OD.ProductName == "Apple"
              select order).Distinct().ToList();

//or this solution
orders = context.Set<Order>().Include(p => p.OrderDetails)
   .Where(x => x.CreatedBy == "Jason" && x.OrderDetails.Any(y => y.ProductName == "Apple"))
   .ToList();    

【讨论】:

  • 非常感谢您分享您的答案!有什么方法可以对同一场景使用“包含”查询?或者说 linq-to-sql 可能比“包含”查询更好,并且是实现这种方法的唯一方法?
  • @KevinDing,如果您想获取OrderDetails 作为最终结果的一部分,您可以Include 他们,如我的回答所示,但如果您只想过滤,则不需要由他们。
  • 非常感谢您提供替代答案!
  • 嗨 Slava,您能帮我看看stackoverflow.com/questions/50733417/… 上的另一个与 EF Core 相关的问题吗?
【解决方案2】:

@Slava 的答案看起来是正确的。但我想扩展他的答案。如果要在查询中使用like,可以使用EF.Functions.Like方法。它在内存和处理复杂表达式方面成本较低。您可以在您的场景中使用相同的,也可以像下面的代码一样。在关系数据库上,这通常直接翻译成 SQL。

var orders = (from O in context.Order
              join OD in context.OrderDetail on O.OrderId equals OD.OrderId
              where EF.Functions.Like(O.CreatedBy, "Jason") && EF.Functions.Like(OD.ProductName, "Apple")
              select order).Distinct().ToList();

【讨论】:

  • 非常感谢您提供“LIKE”命令的扩展用法!
  • @KevinDing 如果对您有帮助,请您为答案投票
猜你喜欢
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
相关资源
最近更新 更多