EF Core多个“ where”未翻译

时间:2019-04-02 13:11:08

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

我有一个数据库模型,我想对它进行过滤(在运行时)其他属性。为此,我有一些方法,每个方法根据属性运行一个“ where”子句,并返回一个IQueryable。问题是该子句无法转换为SQL,因此查询不使用“ WHERE”语句运行,返回整个表,服务器正在执行过滤,这既缓慢又昂贵。

从日志中,我收到一条消息:

  

Microsoft.EntityFrameworkCore.Query:警告:LINQ表达式   “在哪里(新EntityId([ed] .EntityId).Id == __entityId_Id_1)”无法   进行翻译并将在本地进行评估。

我的问题是:我在这里正确吗?如果是的话,我下一步应该看什么?

主要功能

public static EntityDataDTO GetEntityByKey(this IQueryable<EntityDTO> query, IEntityId entityId, EntityTypeDTO type, string key)
{
    return query
        .HasEntity(entityId)
        .HasType(type)
        .HasKey(key)
        .FirstOrDefault();
}

public static EntityDataDTO GetEntity(this IQueryable<EntityDTO> query, IEntityId entityId, EntityTypeDTO type)
{
    return query
        .HasEntity(entityId)
        .HasType(type)
        .FirstOrDefault();
}

子功能

public static IQueryable<EntityDDTO> HasType(this IQueryable<EntityDTO> query, EntityTypeDTO type)
{
    return query.Where(ed => ed.Type == type);
}

public static IQueryable<EntityDTO> HasEntity(this IQueryable<EntityDTO> query, IEntityId entityId)
{
    return query.Where(ed => ed.EntityId.Id == entityId.Id);
}

EntityDTO

public class EntityDTO
    {
        public int Id { get; set; }
        public EntityTypeDTO Type { get; set; }
        public string Key { get; set; }
        public string Value { get; set; }
        public IEntityId EntityId { get; set; }
        public IPartnerId PartnerId { get; set; }
    }

2 个答案:

答案 0 :(得分:2)

我发现您发布的任何代码都没有问题。但是,您忽略了发布HasKey方法的定义,因此我假设问题确实存在。

在任何情况下,警告都会准确告诉您问题代码是什么:new EntityId(ed.EntityId).Id。找到那段代码并更正它。诸如调用新类型之类的东西无法转换为SQL,因此EF必须在内存中运行它。从技术上讲,您可以继续并仅允许EF执行此操作。但是,通常这表明您将要运行效率低下的查询,因此您应该寻找一种更好的方法,而不必在内存中运行该部分查询。

答案 1 :(得分:0)

您可以使用表达式谓词并为自己构建一个常见的可重用表达式的库。这是将其添加到EntityDTO的示例,请注意,它返回一个表达式,而不是实际的IQueryable / IEnumerable:

public partial class EntityDTO
{
  public static Expression<Func<EntityDTO, bool>> HasType(EntityTypeDTO type)
  {
    return ed => ed.Type == type;
  }
  public static Expression<Func<EntityDTO, bool>> HasEntity(IEntityId entityId)
  {
      return ed => ed.EntityId.Id == entityId.Id;
  }
}