Entity Framework Core Linq查询以过滤相关实体。

7

我很久以来一直在想如何在使用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中,它应该是这样的: Hide Copy Code
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)过滤属性,但是我不知道如何处理相关实体,比如在OrderDetail.ProductName上进行Include/ThenInclude过滤。我已经进行了很多研究,但仍然没有头绪,因此最后我只能使用存储过程,这并不是大多数开发人员推荐的方法。
也许可以使用Linq SQL来解决这个问题?
请帮助我更好地理解它!非常感谢每一个愿意分享知识的人!

以下类似的东西不起作用:它具体哪方面出了问题? - mjwills
2个回答

6
你可以将你的 SQL 脚本简单地转换为 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();    

非常感谢您分享您的答案!是否有任何方法可以在相同的情况下使用“Include”查询?或者说,linq-to-sql可能比“Include”查询更好,并且是实现此方法的唯一方法? - Kev D.
@KevinDing,如果你想在最终结果中获取OrderDetails,你可以像我的答案中所示使用Include,但是如果你只想按它们进行过滤,则不需要。 - Slava Utesinov
非常感谢您提供备选答案! - Kev D.
嗨,Slava,你介意帮我看一下另一个关于EF Core的问题吗?链接是https://stackoverflow.com/questions/50733417/entity-framework-core-2-handle-related-entity-save。 - Kev D.

0

@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”命令的扩展用法! - Kev D.
你怎么可以认为 Like 操作符比 = 操作符更省性能呢?因为在使用上,两者是 功能等价 的,都没有使用通配符。所以没有理由使用 Like,反而应该避免使用它,因为它的性能开销更大。此外,在这里提到 Like 没有任何必要,也不是关键点。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接