0

I'm trying to assign a DbSet of class that is inherited from a more generic class. The example below demonstrates what I'm trying to achieve:

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;
}

The Dog, Cat, Pig class is an inherited class of Animal, as follows:

public class Dog : Animal { }

But I am getting a compile-time error of Cannot implicitly convert type DbSet<Dog> to DbSet<Animal>

How can I implement my design without getting the error?

P.S. The code above is just to illustrate what I'm trying to achieve, so forgive me if it doesn't make sense.

Dan
  • 971
  • 1
  • 8
  • 22

2 Answers2

1

Because compiler cant cast derived classes to base class w/o information loss. You simply cant put DbSet of Cat into DbSet of Animal where Cat : Animal

But you CAN put DbSet of Animal into DbSet of Cat

Try this one:

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

And the method:

    private DbSet<T> GetDbSet<T>(T selectedAnimal) where T : Animal
    {
        return this.Set<T>(); //this == EF Context
    }
Szer
  • 3,426
  • 3
  • 16
  • 36
  • This doesn't answer my question. I'm trying to set a DbSet of derived class into a DbSet of base class, which according to @ChrisV, covariance. I don't see how your answer can do that, thanks anyway! – Dan Jan 28 '15 at 08:14
1

What you're referring to is called covariance. In C# only interfaces can be covariant. So IEnumerable<Cat> is a subtype of IEnumerable<Animal>. The problem with declaring a DbSet<Animal> and then putting a variable of type DbSet<Cat> in it is that a variable of type DbSet<Animal> has methods that allow, for instance, adding an Animal entity. That Animal might be a Dog. But the variable you put in there was a DbSet<Cat> and that can't contain Dog. It would be a violation of strong typing.

ChrisV
  • 1,309
  • 9
  • 15
  • So according to what you are saying, will it work if I change `Animal` into an interface? It doesn't seem to work even after changing `Animal` from a class to interface. – Dan Jan 28 '15 at 06:59
  • No, I'm saying that it would work if `DbSet` were an interface (and if it were declared in a certain manner, read the wiki page on covariance and contravariance). What you're trying to do can't be done. – ChrisV Jan 28 '15 at 11:19