DbSet<T>
НЕ МОЖЕТ быть со-вариантом. Во-первых, это потому, что в C# классы не могут быть ко-вариантными ... только интерфейсами. Во-вторых, поскольку DbSet<T>
имеет как ко-вариантные, так и контра-вариантные методы.
Примите следующие два примера.
DbSet<CategoryType> set = context.Set<CategoryType>();
IQueryable<IItemType> query = set.Where(x => x.Foo == Bar);
Итак, мы знаем, за то, что все CategoryType
s являются IItemType
, поэтому мы знаем, что это всегда может работать.
Однако, наоборот, попробовать это ...
DbSet<CategoryType> set = context.Set<CategoryType>();
IItemType newItemType = new ProductType();
set.Add(newItemType); // Compiler error.
Не все IItemType
s являются CategoryType
. Поэтому, если бы мы могли наложить DbSet<CategoryType>
на DbSet<IItemType>
, мы бы получили ошибки времени выполнения при добавлении ... Поскольку компилятор знает, что это может не всегда работать, оно не позволит вам делать кастинг.
Однако есть интерфейсы, которые DbSet<T>
действительно позволяет Соотношение. Например, вы можете попробовать его отличить от IQueryable<IItemType>
.
Однако это звучит, как вы пытаетесь запросить против DbSet с помощью запроса к интерфейсу ... попробуйте следующее
DbSet<CategoryType> set = context.Set<CategoryType>();
IQueryable<IItemType> cast = set.OfType<IITemType>(); //(or .Cast<>() works too)
IQueryable<IItemType> query = cast.Where(x => x ....);
Означает ли, что 'Cast' вызов добавляется к' Expression' перед тем его исполнение? Таким образом, EF пытается перевести вызов «Cast» в какой-то SQL и, очевидно, не может, потому что в базе данных нет «IItemType». –
Да, именно это и происходит. –
-1 DbSet никогда не может быть ковариантным. –
Aron