Entity Framework: запрос нескольких типов

У меня есть модель EF6 code-first с наследованием, например:

[Table("Things")]
abstract class AbstractThing
{
   public int ThingId { get; set; }
   public string Color { get; set; }
}

class Car : AbstractThing
{
   public string Brand { get; set; }
}

class Balloon : AbstractThing
{
   public double Price { get; set; }
}

class Animal : AbstractThing
{
   public int LegCount { get; set; }
}

Я использую таблицу для иерархии, поэтому моя таблица «Вещи» будет иметь столбцы:

  • Идентификатор вещи: целое
  • Цвет: строка
  • Марка: строка
  • Цена: двойная
  • LegCount : целое
  • Дискриминатор: строка

Теперь я хочу запросить объекты определенного типа, но этот список типов является динамическим. Например. Я хочу все красные вещи, которые являются автомобилями или воздушными шарами. В SQL это довольно легко сделать, так как я мог бы просто скомпилировать предложение where Discriminator in ('Car', 'Ballon').

Проблема здесь в том, что, насколько мне известно, единственный способ фильтровать по типу в EF Linq2SQL — использовать метод .OfType (или использовать определенные коллекции). Но затем я возвращаю отфильтрованный список, содержащий только этот тип, я не могу использовать предложение «ИЛИ» или «В». Я не могу понять, как это сделать, не запрашивая явно каждый набор и не создавая объединение:

var queryable = Enumerable.Empty<Thing>().AsQueryable();

if (typesRequested.Contains(typeof(Car)))
{
   queryable = queryable.Union(context.Things.OfType<Car>());
}
if (typesRequested.Contains(typeof(Balloon)))
{
   queryable = queryable.Union(context.Things.OfType<Balloon>());
}
if (typesRequested.Contains(typeof(Animal)))
{
   queryable = queryable.Union(context.Things.OfType<Animal>());
}

Поскольку в моей реальной модели у меня гораздо больше унаследованных типов, этот подход не так осуществим. Обходной путь, который у меня есть сейчас, состоит в том, чтобы иметь пользовательский столбец «тип», который дублирует столбец «Дискриминатор», но это подвержено ошибкам и создает шаблонный код.

Есть ли другой способ динамически ограничить запрос, чтобы он возвращал только определенный набор типов?


person Efrain    schedule 27.02.2018    source источник


Ответы (1)


Это кажется возможным с EF Core: свойство «Дискриминатор» теперь доступно как Shadow Property. (https://docs.microsoft.com/en-us/ef/core/modeling/relational/inheritance#configuring-the-distributor-property )

i.e.:

var types = typesRequested.Select(x => x.Name).ToArray();
var filteredByType = context.Things.Where(tng => 
                 types.Contains(EF.Property<string>(tng, "Discriminator")));
person Efrain    schedule 17.09.2018