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

EF Core中如何用List<BucketList>多条件匹配查询SQL表数据

问题描述

需要使用Entity Framework Core通过LINQ从对应实体类Table1EntityClass的SQL表中,查询与List<BucketList>对象组合条件匹配的数据。

实体类定义

public class Table1EntityClass
{
    public int id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
    public int Quantity { get; set; }
}

public class BucketList 
{
    public string Name { get; set; }
    public string Price { get; set; }
    public string Category { get; set; }
}

需求说明

查询table1中Name、Price、Category与List中某一对象对应值完全匹配的行。

示例数据:

表中数据:

  • Name: Apple, Description: A fruit, Price: 30, Category: fruits, Quantity:10
  • Name: Apple, Description: A fruit, Price:20, Category: fruits, Quantity:10
  • Name: Orange, Description: A fruit, Price:50, Category: fruits, Quantity:10
  • Name: banana, Description: A fruit, Price:30, Category: fruits, Quantity:10
  • Name: Onion, Description: A vegetable, Price:30, Category: vegetable, Quantity:5

List包含对象:

  • Apple, 30, fruits
  • Onion, 30, vegetable

期望结果:第1行和第5行数据。

尝试的LINQ查询及错误

尝试了以下代码,但EF Core无法翻译该查询:

var result = dbContext.table1
                      .Where(item => bucketLists.Any(bucketvalue =>
                                         item.Name == bucketvalue.Name  &&
                                         item.Price == bucketvalue.Price &&
                                         item.Category == bucketvalue.Category))
                      .ToList();

错误提示:LINQ查询无法被翻译,需改写为可翻译形式,或显式调用AsEnumerable等启用客户端评估。


解决方案

前置注意事项

首先要处理类型不匹配问题:BucketList的Price是string类型,而Table1EntityClass的Price是decimal,需要先把BucketList中的Price转换为decimal(可根据实际场景添加转换失败的异常处理),避免后续查询出错。

方法1:构建匿名类型条件集合,使用Contains匹配组合条件

先将bucketLists转换为包含Name、Price(已转decimal)、Category的匿名类型集合,再用Contains匹配组合条件。EF Core能将这种写法翻译为SQL中的组合IN子句,完全在数据库端执行:

// 转换BucketList并处理Price类型,假设Price均可正常转换,可按需添加异常捕获
var filterItems = bucketLists.Select(b => new 
{
    b.Name,
    Price = decimal.Parse(b.Price),
    b.Category
}).ToList();

var result = dbContext.table1
    .Where(item => filterItems.Contains(new 
    {
        item.Name,
        item.Price,
        item.Category
    }))
    .ToList();

方法2:动态构建OR条件组合

如果匿名类型的方式不适用,可手动构建多个OR条件,每个条件对应BucketList中的一个对象:

var predicate = PredicateBuilder.False<Table1EntityClass>();
foreach (var bucket in bucketLists)
{
    var name = bucket.Name;
    var price = decimal.Parse(bucket.Price);
    var category = bucket.Category;
    predicate = predicate.Or(item => 
        item.Name == name && 
        item.Price == price && 
        item.Category == category);
}

var result = dbContext.table1.Where(predicate).ToList();

这里需要用到PredicateBuilder,可以自己实现一个简易版本:

public static class PredicateBuilder
{
    public static Expression<Func<T, bool>> False<T>() => f => false;
    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
    {
        var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
    }
}

方法3:客户端过滤(仅小数据量场景使用)

如果表数据量极小,也可以先将全表数据加载到内存,再在客户端过滤,但这种方式会占用较多内存,大数据场景下性能极差,谨慎使用:

var result = dbContext.table1.AsEnumerable()
    .Where(item => bucketLists.Any(bucketvalue =>
        item.Name == bucketvalue.Name &&
        item.Price == decimal.Parse(bucketvalue.Price) &&
        item.Category == bucketvalue.Category))
    .ToList();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:01:29