【问题标题】:How do I DRY query logic between IEnumerable and IQueryable?如何在 IEnumerable 和 IQueryable 之间干燥查询逻辑?
【发布时间】:2020-10-31 16:51:12
【问题描述】:

给定两个实体 EntityOneEntityTwo

public class EntityOne
{
    public string Title { get; set; }
    public bool IsSomething { get; set; }
}
public class EntityTwo
{
    ...

    public virtual IEnumerable<EntityOne> EntityOnes { get; set; }
}

还有一个EntityOneFilter 对象,例如:

public class EntityOneFilter
{
    public EntityOneFilter(string? query, bool? isSomething, ...)
    {
        ...
    }
    
    public string? Query { get; }
    public bool? IsSomething { get; }
}

我想重用可以同时应用于IEnumerable&lt;EntityOne&gt;IQueryable&lt;EntityOne&gt; 的查询逻辑:

(filter.Query == null || EF.Functions.Like(entity.Title, $"%{filter.Query}%"))
    && (!filter.IsSomething.HasValue || entity.IsSomething == filter.IsSomething.Value)
    && ...

这样它就可以应用于来自DbContextIQueryables:

dbContext.EntityOnes.Where(<something with filter>).FirstAsync();

还有IEnumerable&lt;EntityOne&gt;,它显示为EntityTwo的一对多集合:

dbContext.EntityTwos
    .Where(e2 => e2.EntityOnes.Where(<something with filter>).Any())
    .FirstAsync();

我怎样才能做到这一点?

【问题讨论】:

  • 您是否尝试过使用entity.Title.Contains(filter.Query)?此外,您应该将filter.Queryfilter.IsSomething 分配给要在查询中使用的局部变量,这样EF 就不会抱怨翻译EntityOneFilter
  • @juharr 感谢.Contains 提示。目前,它似乎根本没有抱怨这一点。它将它们翻译为好像它们是两个自变量一样。但是,是的,表达本身不是问题。它按预期工作。
  • 我觉得你应该看看Linqkit,例如从here开始。
  • 我所做的是使用 .AsEnumerable() 方法将 IQueryable 转换为 IEnumerable。然后我将该结果传递给其他各种类以增强过滤器。那是可行的吗?
  • 您可以通过 AsQueryable 方法将 IEnumerable 转为 IQueryable。但无论如何,它不适用于仅针对 SQL 翻译的 EF.Functions。

标签: c# linq .net-core entity-framework-core npgsql


【解决方案1】:

按照 cmets 的建议,我只需要使用:

dbContext.EntityTwos
    .Where(e2 => e2.EntityOnes
        .AsQueryable()
        .Where(expression).Any())
    .FirstAsync();

其中expressionExpression&lt;Func&lt;EntityOne, bool&gt;&gt;

【讨论】:

    猜你喜欢
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    • 2021-01-23
    • 2015-02-11
    相关资源
    最近更新 更多