You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Entity Framework Core 6中实现带可选Where条件的查询

在EF Core 6中实现可选WHERE条件查询的原生方案

针对将内嵌SQL的可选WHERE逻辑迁移到EF Core 6的需求,以下是几种基于EF Core原生功能的可行方案,无需依赖第三方工具:

方案1:基于实体对象的自动筛选

如果你的筛选条件和实体结构匹配,可以通过反射动态生成筛选表达式,自动忽略空值或默认值属性,实现类似"传入实体作为筛选条件"的效果。

扩展方法实现

using System.Linq.Expressions;

public static class QueryableExtensions
{
    public static IQueryable<T> WhereByNonEmptyProperties<T>(this IQueryable<T> query, T filter) where T : class
    {
        if (filter == null) return query;

        var parameter = Expression.Parameter(typeof(T), "entity");
        Expression combinedCondition = null;

        foreach (var property in typeof(T).GetProperties())
        {
            var propertyValue = property.GetValue(filter);
            if (propertyValue == null) continue;

            // 跳过值类型的默认值(如int的0、bool的false,可根据业务调整)
            if (property.PropertyType.IsValueType && 
                Equals(propertyValue, Activator.CreateInstance(property.PropertyType)))
            {
                continue;
            }

            // 构建属性等于值的表达式
            var propertyAccess = Expression.Property(parameter, property.Name);
            var constantValue = Expression.Constant(propertyValue);
            var equalsExpr = Expression.Equal(propertyAccess, constantValue);

            combinedCondition = combinedCondition == null 
                ? equalsExpr 
                : Expression.AndAlso(combinedCondition, equalsExpr);
        }

        if (combinedCondition != null)
        {
            var filterLambda = Expression.Lambda<Func<T, bool>>(combinedCondition, parameter);
            query = query.Where(filterLambda);
        }

        return query;
    }
}

用法示例

假设你有Customer实体:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? Age { get; set; }
    public string City { get; set; }
}

查询时只需构造筛选实体,空属性会被自动忽略:

var filter = new Customer { Name = "Alice", City = "London" };
var customers = _dbContext.Customers
    .WhereByNonEmptyProperties(filter)
    .ToList();

这会生成等价于WHERE Name = 'Alice' AND City = 'London'的SQL。

方案2:直接传入表达式树

如果需要支持复杂的自定义筛选逻辑,直接让调用方传入Expression<Func<T, bool>>类型的条件,这是EF Core最原生的用法,灵活性最高。

实现代码

public class CustomerRepository
{
    private readonly AppDbContext _dbContext;

    public CustomerRepository(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IQueryable<Customer> GetCustomers(Expression<Func<Customer, bool>> filter = null)
    {
        var query = _dbContext.Customers.AsQueryable();
        if (filter != null)
        {
            query = query.Where(filter);
        }
        return query;
    }
}

用法示例

调用时可以传入任意复杂的条件:

// 查询年龄大于30且来自纽约的客户
var customers = _customerRepository.GetCustomers(
    x => x.Age > 30 && x.City == "New York" && x.CreatedDate > DateTime.Now.AddMonths(-6)
).ToList();

// 不传条件则查询全部
var allCustomers = _customerRepository.GetCustomers().ToList();

方案3:链式拼接筛选条件

对于已知固定筛选参数的场景,直接通过链式调用Where方法拼接条件,代码直观且性能最优,无需反射或表达式树动态生成。

实现代码

public IQueryable<Customer> GetFilteredCustomers(string name = null, int? age = null, string city = null)
{
    var query = _dbContext.Customers.AsQueryable();

    if (!string.IsNullOrWhiteSpace(name))
    {
        query = query.Where(x => x.Name.Contains(name));
    }
    if (age.HasValue)
    {
        query = query.Where(x => x.Age == age.Value);
    }
    if (!string.IsNullOrWhiteSpace(city))
    {
        query = query.Where(x => x.City == city);
    }

    return query;
}

用法示例

// 只按城市筛选
var londonCustomers = GetFilteredCustomers(city: "London").ToList();

// 按姓名和年龄筛选
var alice30 = GetFilteredCustomers(name: "Alice", age: 30).ToList();

方案选择建议

  • 若筛选条件与实体结构高度匹配,优先用方案1,简化调用方代码。
  • 若需要支持复杂、灵活的自定义条件,选择方案2。
  • 若筛选参数固定且明确,用方案3,代码可读性和性能最佳。

内容的提问来源于stack exchange,提问作者Ken

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:52:43