用EF Core组成OR查询

时间:2019-02-26 17:01:37

标签: c# entity-framework-core npgsql

我有一个DbQuery,我试图根据用户提供的各种(可选)参数进行过滤。我正在尝试使用LINQ来组成查询,以解决此问题,但是遇到了麻烦,所以这有点像是两个伙伴。

Postgres: 我正在使用postgres,所以我有一个数组列,并且我希望能够基本完成useCaseArray && entity.useCases。但是,EF提供程序当前不支持此功能。

如果不想避免,我不想在原始sql中编写整个内容,所以我想我可以在这样的地方做一个非常丑陋的事情:

WHERE (useCases.Contains(x) || useCases.Contains(y) ...)

但是我不知道如何用LINQ 组成。我知道您可以内联进行OR,例如

query.Where(item => item.cases.Contains(x) || item.cases.Contains(y))

但是我不能那样写,因为我需要遍历/循环 包含我的X和Y的数组。有人知道我该怎么做吗?

foreach(var usecase in request.UseCases) 
{
  query = query.Where(item => item.UseCases.Contains(usecase));
}

当我希望整个子集成为一个OR时,这只会生成一系列AND。

我希望我已经适当地解释了这一点!另外,我很希望能够在原始SQL中注入单个WHERE子句组件,但我认为这会导致EF Core爆炸,这听起来像是在执行FromSQL并不仅仅支持SELECT。

更新:

根据评论,我尝试了以下操作:https://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/效果非常好:

var useCaseQuery = request.UseCases
  .Select(useCase => PredicateBuilder.Create<MyEntity>(entity => entity.UseCases.Contains(useCase)))
  .Aggregate(PredicateBuilder.Or);

query = query.Where(useCaseQuery);

从某种意义上说,这很棒,但是EF Core仍然不喜欢它:

The LINQ expression 'where ({[assumption].UseCases => Contains(__useCase_3)} OrElse {[assumption].UseCases => Contains(__useCase_4)})' could not be translated and will be evaluated locally.

我认为这对我来说很好,但是原始问题仍然存在,我希望它可以在数据库上运行。

1 个答案:

答案 0 :(得分:1)

因此,在发表了一些有用的评论之后,我尝试了FromSql

if (request.UseCases != null && request.UseCases.Count > 0)
{
  // I know UseCases is a List<int> hence why I'm just joining without escaping.
  query = query.FromSql("SELECT * FROM my_table WHERE ARRAY[" + String.Join(',', request.UseCases) + "] && use_cases");
}

我不是100%这样,因为现在我的服务知道我的数据库表和字段名,这几乎使ORM的用途无效。但是,对于这种特定情况,它可以满足我的需要,我可以像这样继续撰写:

if (request.Groups != null && request.Groups.Count > 0)
{
  query = query.Where(data => request.Groups.Contains(data.GroupId));
}

if (!String.IsNullOrWhiteSpace(request.Title))
{
  query = query.Where(data => EF.Functions.ILike(data.Name, $"%{request.Title}%"));
}

产生的SQL是这样的:

SELECT my_table.classes, my_table."group", my_table.group_id, my_table.id, my_table.name, my_table.use_cases
FROM (
    SELECT * FROM my_table WHERE ARRAY[7,4] && use_cases
) AS assumption
WHERE my_table.group_id IN (7) AND (my_table.name ILIKE @__Format_3 ESCAPE '' = TRUE)
ORDER BY my_table.name DESC

在Postgres EF Core驱动程序更新之前,这可能是我能做的最好的事情。