EF Core множественное "где" не переведены - PullRequest
1 голос
/ 02 апреля 2019

У меня есть модель БД, которую я хочу фильтровать (во время выполнения) по различным атрибутам.Для этого у меня есть методы, каждый из которых выполняет предложение 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 ]

2 голосов
/ 02 апреля 2019

Не вижу проблем с кодом, который вы опубликовали. Однако вы забыли опубликовать определение вашего HasKey метода, поэтому я предполагаю, что проблема действительно есть.

В любом случае, предупреждение говорит вам, что именно является проблемным кодом: new EntityId(ed.EntityId).Id. Найдите этот кусок кода и исправьте его. Нечто подобное вызову new up типа не может быть переведено в SQL, поэтому EF должен выполнить это в памяти. Технически, вы можете продолжить и просто позволить EF сделать это. Тем не менее, это, как правило, признак того, что вы собираетесь выполнять неэффективные запросы, поэтому вы должны искать лучший способ, который не требует выполнения этой части запроса в памяти.

0 голосов
/ 02 апреля 2019

Вы можете использовать предикаты выражений и создать себе библиотеку общих многократно используемых выражений.Вот пример добавления этого к вашему 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;
  }
}
...