1

I am trying to achieve an abstraction in ASP.NET MVC with C#.

I have a base entity controller which should do most of the job for its derived classes(entities). In it, I have a problematic method which should return the database context of each table(I am not using any DB frameworks like EF). Here is the method:

protected abstract DbContext<EntityViewModel> CreateContext();

So, say I have a Category table, the method should be implemented:

protected override DbContext<EntityViewModel> CreateContext()
{
    return new CategoryDbContext();
}

But C# says I can't implicitly cast it, etc...

Here are the context classes:

public abstract class DbContext<T>
{
    public abstract void Create(T entity);

    public abstract List<T> Read(ModifyData data);

    public abstract void Update(T entity);

    public abstract void Delete(T entity);
}

public class CategoryDbContext : DbContext<CategoryViewModel>
{
    public override void Create(CategoryViewModel entity)
    {
    }

    public override List<CategoryViewModel> Read(ModifyData data)
    {
    }

    public override void Update(CategoryViewModel entity)
    {
    }

    public override void Delete(CategoryViewModel entity)
    {
    }
}

What am I doing wrong here?

Toshkuuu
  • 805
  • 1
  • 7
  • 9
  • (The duplicate is about list rather than DbContext, but it's basically the same issue...) – Jon Skeet Jul 24 '15 at 07:57
  • what is the relationship between CategoryViewModel & EntityViewModel – harishr Jul 24 '15 at 07:57
  • method `CreateContext` has to return `DbContext` or inherited object, but your `CategoryDbContext` has different type - `DbContext` – Disappointed Jul 24 '15 at 07:58
  • entity is the parent, category is a derived child @entre – Toshkuuu Jul 24 '15 at 07:59
  • 1
    if category is child of entity it doesn't mean that `DbContext` is child of `DbContext` – Disappointed Jul 24 '15 at 08:00
  • @Disappointed but what about `CategoryDbContext` ? It derives from `DbContext`. I want to cast `DbContext` to `CategoryDbContext` – Toshkuuu Jul 24 '15 at 08:17
  • @JonSkeet While this question is a duplicate there is still a way to help the poster with his problem which is a tad different from the fruit bowl problem. Where the List class is a framework class, he has an opportunity here to redefine his class to work for him in a way that may be suitable to solve his problem. – Tyree Jackson Jul 24 '15 at 08:54
  • @Toshkuuu Unfortunately with this question being marked a duplicate, I cannot provide you with a formatted answer. Try making the signature of your base entity controller look something like this: "public abstract class EntityController where TDbContext : DbContext where TEntityViewModel : EntityViewModel {}". Then change your CreateContext method signature to "protected abstract TDbContext CreateContext();" – Tyree Jackson Jul 24 '15 at 08:57
  • @JonSkeet Now that I think about it further, this question is NOT a duplicate. The poster has a design issue where his method's return type is incorrect. The intent of his code does not seem to indicate that he actually wants to work with DbContext, but rather with the individual generic derivatives of that type. Is there a way to vote to unmark this question as a duplicate? – Tyree Jackson Jul 24 '15 at 09:15
  • @TyreeJackson: It *could* be unmarked as a duplicate, but I still think it is - the OP is asking why they can't treat a `DbContext` as a `DbContext`, and once you understand why a `List` isn't a `List`, you know the answer to this question as well. Note that the OP can't change `DbContext` to be covariant, as a) it's a class; b) `T` goes "in and out". They may be able to change the controller class, of course... – Jon Skeet Jul 24 '15 at 09:22
  • Many, many thanks to @TyreeJackson, my app is now up and running as intended. And no, I don't consider my question a duplicate, the one provided as such is way different, but this might be due the way I explained it. Anyways, TyreeJackson's answer is the correct one here. – Toshkuuu Jul 24 '15 at 09:45
  • @Toshkuuu: It's not different if your question was why the cast didn't work. Do you now understand why the cast didn't work? If your question was really "How can I design my controller to avoid this problem" then that *wouldn't* have been a duplicate - you could edit this question (with more details of the controller, which you haven't specified at all here) and *then* it would make sense to reopen. As it is, the question you're asking really *is* a duplicate. – Jon Skeet Jul 24 '15 at 09:58
  • @TyreeJackson: Well, I didn't vote to *delete* the question. The duplicate is meant to help the OP to realize that the question they actually *asked* has already been answered. Note that the bigger aim of Stack Overflow is to build a repository of useful questions and answers - an answer to the question actually asked would be a duplicate. That's why I've suggested that the OP should edit the question to one which *isn't* a duplicate - at which point it would make sense to reopen it, answer it, and the world would be a better place. Unfortunately, the OP has chosen not to do this :( – Jon Skeet Jul 24 '15 at 13:37
  • @jonskeet Sometimes we have to read between the lines. As an architect supporting several developers, if one asked a question like this and then I proceed to give him the answer listed on the dup, I would not be doing part of job. Instead I've been far more successful following up questions like that by asking, "what are you trying to do" rather than simply answering questions directly. If we summarily dismiss questions like this I fear we miss opportunities to help others truly understand solutions. In my comment I only gave the answer. In an expanded answer I could have said why. – Tyree Jackson Jul 24 '15 at 13:41
  • @Tyree: And again, if the question were edited to not be a dupe, it would be reasonable to reopen it. – Jon Skeet Jul 24 '15 at 13:52

0 Answers0