EF C# 构建在 WHERE 子句中具有多个谓词的复杂查询
EF C# Building complex query having multiple predicates within WHERE clause
我的 API 查询的一部分是要在 select 查询中使用的 ID 数组。以下是查询的创建方式:
var budget_query = _context.Budgets
.Where(_ => _.IdOwner == q.IdOwner)
.Where(_ => _.Month >= startdate && _.Month <= enddate)
.Where(_ => _.IsDeleted == 0);
if (q.IsCategory != 1)
budget_query = budget_query.Where(_ => _.IsUncat == 0);
if (q.IdCurrency != null && q.IdCurrency != 0)
budget_query = budget_query.Where(_ => _.IdCurrency == q.IdCurrency);
if (q.IdTagSel.Length > 0)
foreach (var sel in q.IdTagSel)
budget_query = budget_query.Where(_ => _.IdTag == sel);
它会导致空响应,因为显然一个记录的字段不能有很多不同的值,在这种情况下它会创建 SQL 查询,例如:
SELECT * FROM budgets WHERE IdTag = value1 AND IdTag = value2, etc
然而,我想要这样的结果:
SELECT * FROM budgets WHERE (IdTag == value1 OR IdTag == value2)
是否有任何简单的方法可以使用 LINQ 表达式实现此目的?
编辑
在表达方式的情况下对我有用:
budget_query = budget_query.Where(_ => q.IdTagSel.Any(x=>x ==_.IdTag));
但是当我尝试将它用于我在以下代码中具有相同索引的第二个查询时:
var trans_query = _context.Transactions
.Where(_ => _.TransactionDate > startdate && _.TransactionDate < enddate)
.Where(_ => _.IsDeleted == 0)
.Where(_ => _.IdOwner == q.IdOwner)
.Where(_ => _.IsCredit == q.IsIncome);
if (q.IdTagSel.Length > 0)
trans_query = trans_query.Where(_ => q.IdTagSel.Any(y => y == _.IdTag));
if (q.IdCurrency != null && q.IdCurrency != 0)
trans_query = trans_query.Where(_ => _.IdCurrency == q.IdCurrency);
var trans = trans_query.OrderBy(_ => _.TransactionDate).ToList();
我收到以下异常:
"The LINQ expression 'DbSet<Transaction>()\n .Where(t => t.TransactionDate > __startdate_0 && t.TransactionDate < __enddate_1)\n .Where(t => (int)t.IsDeleted == 0)\n .Where(t => t.IdOwner == __q_IdOwner_2)\n .Where(t => (Nullable<int>)(int)t.IsCredit == __q_IsIncome_3)\n .Where(t => __q_IdTagSel_4\n .Any(y => (Nullable<int>)y == t.IdTag))' could not be translated.
我尝试对其进行调试,一切看起来都正常 - 所有本地人都很好并且与第一种情况相同。现在,我真的很困惑。有什么想法会导致这种差异吗?
任何 Where(...)
都会创建一个 AND
条件。您需要的是将您的 foreach
更改为 .Any()
或 Contains()
条件。不确定哪个对 EF
是正确的
if (q.IdTagSel.Length > 0)
budget_query = budget_query.Where(_ => q.IdTagSel.Contains(_.IdTag));
//--- or
if (q.IdTagSel.Length > 0)
budget_query = budget_query.Where(_ => q.IdTagSel.Any(x => x == _.IdTag));
应该创建
SELECT * FROM budgets WHERE IdTag IN (value1, value2)
我的 API 查询的一部分是要在 select 查询中使用的 ID 数组。以下是查询的创建方式:
var budget_query = _context.Budgets
.Where(_ => _.IdOwner == q.IdOwner)
.Where(_ => _.Month >= startdate && _.Month <= enddate)
.Where(_ => _.IsDeleted == 0);
if (q.IsCategory != 1)
budget_query = budget_query.Where(_ => _.IsUncat == 0);
if (q.IdCurrency != null && q.IdCurrency != 0)
budget_query = budget_query.Where(_ => _.IdCurrency == q.IdCurrency);
if (q.IdTagSel.Length > 0)
foreach (var sel in q.IdTagSel)
budget_query = budget_query.Where(_ => _.IdTag == sel);
它会导致空响应,因为显然一个记录的字段不能有很多不同的值,在这种情况下它会创建 SQL 查询,例如:
SELECT * FROM budgets WHERE IdTag = value1 AND IdTag = value2, etc
然而,我想要这样的结果:
SELECT * FROM budgets WHERE (IdTag == value1 OR IdTag == value2)
是否有任何简单的方法可以使用 LINQ 表达式实现此目的?
编辑
在表达方式的情况下对我有用:
budget_query = budget_query.Where(_ => q.IdTagSel.Any(x=>x ==_.IdTag));
但是当我尝试将它用于我在以下代码中具有相同索引的第二个查询时:
var trans_query = _context.Transactions
.Where(_ => _.TransactionDate > startdate && _.TransactionDate < enddate)
.Where(_ => _.IsDeleted == 0)
.Where(_ => _.IdOwner == q.IdOwner)
.Where(_ => _.IsCredit == q.IsIncome);
if (q.IdTagSel.Length > 0)
trans_query = trans_query.Where(_ => q.IdTagSel.Any(y => y == _.IdTag));
if (q.IdCurrency != null && q.IdCurrency != 0)
trans_query = trans_query.Where(_ => _.IdCurrency == q.IdCurrency);
var trans = trans_query.OrderBy(_ => _.TransactionDate).ToList();
我收到以下异常:
"The LINQ expression 'DbSet<Transaction>()\n .Where(t => t.TransactionDate > __startdate_0 && t.TransactionDate < __enddate_1)\n .Where(t => (int)t.IsDeleted == 0)\n .Where(t => t.IdOwner == __q_IdOwner_2)\n .Where(t => (Nullable<int>)(int)t.IsCredit == __q_IsIncome_3)\n .Where(t => __q_IdTagSel_4\n .Any(y => (Nullable<int>)y == t.IdTag))' could not be translated.
我尝试对其进行调试,一切看起来都正常 - 所有本地人都很好并且与第一种情况相同。现在,我真的很困惑。有什么想法会导致这种差异吗?
任何 Where(...)
都会创建一个 AND
条件。您需要的是将您的 foreach
更改为 .Any()
或 Contains()
条件。不确定哪个对 EF
if (q.IdTagSel.Length > 0)
budget_query = budget_query.Where(_ => q.IdTagSel.Contains(_.IdTag));
//--- or
if (q.IdTagSel.Length > 0)
budget_query = budget_query.Where(_ => q.IdTagSel.Any(x => x == _.IdTag));
应该创建
SELECT * FROM budgets WHERE IdTag IN (value1, value2)