2015-01-28 3 views
0

Я пытаюсь назначить класс DbSet, который наследуется от более общего класса. В приведенном ниже примере показано, что я пытаюсь достичь:Entity Framework Generic Inheritance

DbSet<Animal> dbSet; 

switch (selectedAnimal) 
{ 
    case "Dog": 
     dbSet = _Context.Dog; // DbSet<Dog> 
     break; 
    case "Cat": 
     dbSet = _Context.Cat; // DbSet<Cat> 
     break; 
    case "Pig": 
     dbSet = _Context.Pig; // DbSet<Pig> 
     break; 
} 

Dog, Cat, Pig класс унаследованный класс Animal следующим образом:

public class Dog : Animal { } 

Но я получаю compile- временная ошибка Cannot implicitly convert type DbSet<Dog> to DbSet<Animal>

Как реализовать проект без получения ошибки?

P.S. Вышеприведенный код просто иллюстрирует то, что я пытаюсь достичь, поэтому простите меня, если это не имеет смысла.

+0

Возможный дубликат http://stackoverflow.com/questions/19082671/why-isnt-dbset-covariant – ChrisV

+0

Интересный .. Ковариация - это что-то новое для меня, прочитает об этом. – Dan

ответ

1

Что вы имеете в виду, называется ковариацией. В C# только интерфейсы могут быть ковариантными. Таким образом, IEnumerable<Cat> является подтипом IEnumerable<Animal>. Проблема с объявлением DbSet<Animal>, а затем вставка переменной типа DbSet<Cat> в нее состоит в том, что переменная типа DbSet<Animal> имеет методы, которые позволяют, например, добавлять объект Animal. Это Animal может быть Dog. Но переменная, которую вы положили, была DbSet<Cat> и не может содержать Dog. Это было бы нарушение сильной типизации.

+0

Итак, согласно тому, что вы говорите, будет ли это работать, если я изменю «Animal» на интерфейс? Кажется, что он работает даже после изменения «Animal» от класса к интерфейсу. – Dan

+0

Нет, я говорю, что это сработает, если 'DbSet' был интерфейсом (и если бы он был объявлен определенным образом, прочитайте страницу вики на ковариации и контравариантности). То, что вы пытаетесь сделать, не может быть сделано. – ChrisV

1

Поскольку компилятор не может использовать производные классы для базового класса без потери информации. Вы просто не можете поместить DbSet из Кота в DbSet о животных, где Cat: Animal

Но вы можете положить DbSet о животных в DbSet Кота

Попробуйте это:

var dbSet = GetDbSet(selectedObject) //selectedObject is Cat,Dog,Pig whatever 

и метод:

private DbSet<T> GetDbSet<T>(T selectedAnimal) where T : Animal 
    { 
     return this.Set<T>(); //this == EF Context 
    } 
+0

Это не отвечает на мой вопрос. Я пытаюсь установить DbSet производного класса в DbSet базового класса, который, согласно @ChrisV, ковариации. Я не понимаю, как ваш ответ может это сделать, спасибо в любом случае! – Dan