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

在Entity Framework中是否可以将where子句的查询字段设为传入参数?

问题解答

该需求完全可以实现,根据你的项目规模和后续扩展需求,可以选择以下3种常用实现方案:

方案1:条件分支判断(适合查询字段少、无频繁扩展需求的场景)

这是最容易理解和维护的方案,通过分支判断给IQueryable拼接不同的查询条件:

[HttpGet]
public IActionResult GetCISCustomers(string Option, string Input)
{
    // 先做白名单校验,避免非法字段查询
    var allowedOptions = new HashSet<string> { "AccountNo", "MeterNo", "Name" };
    if (!allowedOptions.Contains(Option))
    {
        return BadRequest("不支持的查询字段");
    }

    using (var db = new cismodel.eedcbuildingdbContext())
    {
        IQueryable<cismodel.ConsolidatedCustomerDatabase> query = db.ConsolidatedCustomerDatabase;

        // 按Option拼接对应查询条件
        query = Option switch
        {
            "AccountNo" => query.Where(a => a.AccountNo == Input),
            "MeterNo" => query.Where(a => a.MeterNo == Input),
            "Name" => query.Where(a => a.Name == Input),
            _ => query
        };

        // 投影返回结果
        var result = query.Select(a => new
        {
            AccountNo = a.AccountNo,
            MeterNo = a.MeterNo,
            Name = a.Name
        }).ToList();

        string json = Newtonsoft.Json.JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
        return Ok(json);
    }
}

方案2:动态构建表达式树(适合查询字段多、后续会频繁扩展的场景)

通过表达式树动态生成查询条件,新增查询字段时只需要更新白名单即可,不需要修改分支逻辑:
首先在公共类中添加通用扩展方法:

public static class QueryableExtension
{
    public static IQueryable<T> WhereEqual<T>(this IQueryable<T> source, string propertyName, object value)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentNullException(nameof(propertyName));

        // 构建形如 a => a.PropertyName == value 的表达式树
        var parameter = Expression.Parameter(typeof(T), "a");
        var property = Expression.Property(parameter, propertyName);
        var constant = Expression.Constant(value, property.Type);
        var equalExpression = Expression.Equal(property, constant);
        var lambda = Expression.Lambda<Func<T, bool>>(equalExpression, parameter);

        return source.Where(lambda);
    }
}

改造后的接口代码:

[HttpGet]
public IActionResult GetCISCustomers(string Option, string Input)
{
    var allowedOptions = new HashSet<string> { "AccountNo", "MeterNo", "Name" };
    if (!allowedOptions.Contains(Option))
    {
        return BadRequest("不支持的查询字段");
    }

    using (var db = new cismodel.eedcbuildingdbContext())
    {
        var result = db.ConsolidatedCustomerDatabase
                        .WhereEqual(Option, Input)
                        .Select(a => new
                        {
                            AccountNo = a.AccountNo,
                            MeterNo = a.MeterNo,
                            Name = a.Name
                        }).ToList();

        string json = Newtonsoft.Json.JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
        return Ok(json);
    }
}

方案3:使用System.Linq.Dynamic.Core简化动态查询

不想自己写表达式树的场景可以用这个官方维护的类库,先安装NuGet包System.Linq.Dynamic.Core,之后直接用字符串写查询条件即可:

[HttpGet]
public IActionResult GetCISCustomers(string Option, string Input)
{
    var allowedOptions = new HashSet<string> { "AccountNo", "MeterNo", "Name" };
    if (!allowedOptions.Contains(Option))
    {
        return BadRequest("不支持的查询字段");
    }

    using (var db = new cismodel.eedcbuildingdbContext())
    {
        // @0是参数占位符,自动做参数化处理,避免SQL注入
        var result = db.ConsolidatedCustomerDatabase
                        .Where($"{Option} == @0", Input)
                        .Select(a => new
                        {
                            AccountNo = a.AccountNo,
                            MeterNo = a.MeterNo,
                            Name = a.Name
                        }).ToList();

        string json = Newtonsoft.Json.JsonConvert.SerializeObject(result, Newtonsoft.Json.Formatting.Indented);
        return Ok(json);
    }
}

注意事项

  • 所有方案都必须添加Option白名单校验,避免用户传入不存在的字段导致程序报错,也规避潜在的注入风险
  • 上述方案都是通过EF解析生成参数化查询,不要直接将用户输入拼接成原生SQL执行
  • 如果查询字段是数值、日期等非字符串类型,需要提前对Input做类型转换,避免类型不匹配报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:24:05