linq查询中不同级别导航属性的相同where条件的通用表达式函数

Posted

技术标签:

【中文标题】linq查询中不同级别导航属性的相同where条件的通用表达式函数【英文标题】:Common expression function for same where condition at different level navigation properties in linq query 【发布时间】:2022-01-04 01:37:16 【问题描述】:

假设我有一个这样的数据库实体结构

public class Parent

    public virtual Child Child  get; set;


public class Child

    public string Property_1  get; set; 

现在说我有两个这样的 linq 查询

var children = _context.Child.Where(c => c.Property_1 == "X").ToList();
var parents = _context.Parent.Where(p => p.Child.Property_1 == "X").ToList();

这两种情况下的 where 条件在一次意义上是完全相同的。

现在我可以将第一个条件放在一个单独的函数中,该函数将返回 expression,然后我可以在想要选择具有此条件的子项时使用它。

但即使选择父级时的第二个条件也相同,但我仍然无法对 where 子句使用相同的表达式函数,因为它将接受 Child 类型的对象。

所以我的问题是,有没有可能将 where 条件放在一个单独的函数中,以便它可以与两个 linq 查询一起使用?

【问题讨论】:

这个question 很可能与您要查找的内容有关。 【参考方案1】:

你可以使用LINQKit来完成这样的任务,它可以扩展可重用的方法。

public static class QueryExtensions

    [Expandable(nameof(IsXValueImpl))]
    public static bool IsXValue(this Child child)
    
        throw new NotImplementedException();
    

    private static Expression<Func<Cahild, bool>> IsXValueImpl()
    
        return child => child.Property_1 == "X";
    

及用法:

var children = _context.Child.Where(c => c.IsXValue()).ToList();
var parents = _context.Parent.Where(p => p.Child.IsXValue()).ToList();

可以在选项构建期间激活 LINQKit:

builder
    .UseSqlServer(connectionString)
    .WithExpressionExpanding(); // enabling LINQKit extension

或者通过AsExpandable()分机:

var children = _context.Child.AsExpandable().Where(c => c.IsXValue()).ToList();
var parents = _context.Parent.AsExpandable().Where(p => p.Child.IsXValue()).ToList();

【讨论】:

我不想使用外部库。不使用外部库就没有别的办法了吗? 仅在您重复此类功能的情况下。您必须扩展表达式并注入原始表达式树。 EF Core 本身在查询数据时过于笨拙,这就是为什么有很多扩展的原因。我知道至少三个做同样事情的第三方库。

以上是关于linq查询中不同级别导航属性的相同where条件的通用表达式函数的主要内容,如果未能解决你的问题,请参考以下文章

实体框架Linq查询:如何在多个导航属性上从何处选择并从第三个导航属性中选择

LINQ的实例

Linq to Entities 中的动态 where 子句 (OR)

LINQ 实体 Where 子句不在正确位置

LINQ to SQL查询中的C#Dynamic WHERE子句

如何在 linq 查询 c# 中的 WHERE 语句后嵌入动态 OR 条件