наследование entity framework — извлечение только родительского типа

#c# #.net #entity-framework

#c# #.net #entity-framework

Вопрос:

I класс поставщика:

 public class Supplier {
    ....
    ....
    ....
}
  

У меня также есть класс Subjector, а Subjector является поставщиком:

 public class Subcontractor:Supplier {
    ....
    ....
    ....
}
  

В моей базе данных у меня есть таблица поставщиков с данными и другая таблица с полем id, которое действует как внешний ключ к таблице поставщиков, и у меня там также есть данные вложенного компилятора.

В файле edmx entity Framework я объявил отношение наследования: наследование

Теперь я хочу получить всех поставщиков, которые не являются субподрядчиками, поэтому я делаю:

 context.Suppliers.OfType<Supplier>();
  

Но это возвращает также субподрядчиков..

Как я могу получить только поставщиков, которые не являются субподрядчиками?

Ответ №1:

Попробуйте:

 context.Suppliers.Where(s => !(s is Subcontractor));
  

Редактировать

Если у вас есть более одного класса, который является производным от Supplier , единственный вариант с LINQ to Entities выглядит примерно так:

 context.Suppliers.Where(s => !(s is Subcontractor) 
                          amp;amp; !(s is DerivedClass2)
                          amp;amp; !(s is DerivedClass3)); // etc.
  

Entity SQL поддерживает ключевое слово ONLY, которое позволяет запрашивать определенный тип. Но соответствующий аналог недоступен в качестве оператора LINQ.

Здесь представлена реализация OfTypeOnly<TEntity> оператора, но она интенсивно использует информацию метаданных и построение выражений вручную и может быть излишней в простых сценариях.

Комментарии:

1. Что, если субподрядчик — это всего лишь один из 5 типов, производных от поставщика?.. Тогда мне придется добавить 5 wheres.

2. @Naor: К сожалению, кажется, что нет простого способа, смотрите Мою правку выше. По крайней мере, я не смог найти простого решения.

Ответ №2:

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

 public static class MyLinqExtensions
{
    public static IQueryable<T> OfTypeOnly<T>(this IQueryable<T> query)
    {
        Type type = typeof (T);
        IEnumerable<Type> derivedTypes = Assembly
            .GetAssembly(type)
            .GetTypes()
            .Where(t => t.IsSubclassOf(type));

        return query.ExceptTypes(derivedTypes.ToArray());
    }

    public static IQueryable<T> ExceptTypes<T>(this IQueryable<T> query, params Type[] excludedTypes)
    {
        if (excludedTypes == null)
            return query;

        return excludedTypes.Aggregate(query,
            (current, excludedType) => current.Where(entity => entity.GetType() != excludedType));
    }
}
  

Использование:

 // Get only entities of type Supplier, excluding subclasses.
var suppliers = context.Suppliers.OfTypeOnly<Supplier>();
  

Ответ №3:

 context.Suppliers.Where(s => s.GetType() == typeof(Supplier));
  

Комментарии:

1. Это не работает в LINQ для сущностей; GetType не может быть переведено в выражение хранилища.