简体   繁体   English

实体框架Core Linq查询过滤相关实体

[英]Entity Framework Core Linq query to filter related entity

I've been figuring out a long time on how to write a query on filtering related entity through Entity Framework Core while using Include, suppose I have following two class: 我一直在研究如何在使用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; }
}

if I would like to find all orders created by "Jason" and which order detail has product name equals to "Apple" , in sql it would be like: Hide Copy Code 如果我想查找“Jason”创建的所有订单以及哪个订单详细信息的产品名称等于“Apple” ,则在sql中它将是:隐藏复制代码

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

However I am not able to figure out how to write that using EntityFramework, something like below would not work: 但是,我无法弄清楚如何使用EntityFramework编写它,如下所示不起作用:

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

There are scenarios like above, I know how to filter property with base entity class like Order in above example but I don't know how to deal with related entity using Include/ThenInclude like filtering on OrderDetail.ProductName, I've been researching a lot but still no clue therefore at the end I have to use Store procedure instead , which is not recommended by most developers. 有上面的场景, 我知道如何在上面的例子中使用像Order这样的基本实体类来过滤属性,但是我不知道如何使用Include / ThenInclude来处理相关实体,就像在OrderDetail.ProductName上过滤一样, 我一直在研究很多,但仍然没有线索,因此最后我必须使用Store程序 ,这是大多数开发人员不推荐的。

Maybe a linq sql could do that? 也许一个linq sql可以做到这一点?

Please help me understand more about it! 请帮助我了解更多相关信息! Thanks very much to everyone who can share your knowledge! 非常感谢能分享您知识的每个人!

You can simply translate your SQL script to linq: 您可以简单地将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();    

@Slava answer looks correct. @Slava的回答看起来很正确。 But I want to extend his answer. 但我想扩展他的答案。 If you want to use like in your query, you can use EF.Functions.Like method. 如果要在查询中使用like ,可以使用EF.Functions.Like方法。 It is less expensive in terms of memory and handles complex expressions. 它在内存方面较便宜并且处理复杂的表达式。 You can use the same in your scenario also like the below code. 您可以在场景中使用相同的内容,如下面的代码。 On relational databases, this is usually directly translated to SQL. 在关系数据库上,这通常直接转换为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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM