4

Here is a generic example of what I'm doing, what is happening, and what SHOULD be happening:

First, I declare my code first model, something like this:

Context:

namespace Models {
    public class MyContext : DbContext
    {
        public DbSet<ClassA> ClassA { get; set; }
        public DbSet<ClassB> ClassB { get; set; }

        public MyContext()
            : base("name=MyContext")
        {
        }
    }
}

Classes A and B:

namespace Models {
    public class ClassA
    {
        public int ClassAID { get; set; }
        public string BaseAVal { get; set; }
        public virtual ICollection<ClassB> ClassBChildren {get; set; }//Relation Property
    }
    public class ClassB
    {
        public int ClassBID { get; set; }
        public int ClassAID { get; set; }//Foreign Key
        public string BaseBVal { get; set; }
        public virtual ClassA ClassAParent { get; set; }//Relation Property
    }
}

Now elsewhere, in another namespace, I have classes for a different purpose that derive from the model classes.

Derived Classes:

namespace CalculatedModels {
    public class DerivedClassA : ClassA
    {
        string SecondAVal { get; set; }
        public static DerivedClassA fromDBItem(ClassA dbItem) {
            //Create a DerivedClassA
            //Copy over inherited properties from dbItem (via Reflection)
            //Calculate its non-inherited properties
            //return it
        }
        public ClassA toDBItem() {
            //Create a ClassA
            //Copy over inherited properties from this (via Reflection)
            //return it
        }
    }
    public class DerivedClassB : ClassB
    {
        string SecondBVal { get; set; }
        //Conversion functions similar to those in DerivedClassA go here...
    }
}

The problem arises when I have EntityFramework generate the database from this model. I DON'T want it to include ANYTHING from the derived classes. They are NOT for the database to concern itself with! Why else would I put them in a completely different namespace and make the collections in the context be of the non-extended base types? Tables SHOULD look like this:

Table: ClassA
    ---Columns---
    ClassAID (PrimaryKey, int, not null)
    BaseAVal (nvarchar(max), null)

Table: ClassB
    ---Columns---
    ClassBID (PrimaryKey, int, not null)
    ClassAID (ForeignKey, int, not null)
    BaseBVal (nvarchar(max), null)

But EF insists on ruining my intended schema by adding the newly declared properties of the the derived classes like so:

Table: ClassA
    ---Columns---
    ClassAID (PrimaryKey, int, not null)
    BaseAVal (nvarchar(max), null)
    SecondAVal (nvarchar(max), null) --This should NOT be here!!
    Discriminator (nvarchar(128)) --Neither should this!!

Table: ClassB
    ---Columns---
    ClassBID (PrimaryKey, int, not null)
    ClassAID (ForeignKey, int, not null)
    BaseBVal (nvarchar(max), null)
    SecondBVal (nvarchar(max), null) --This should NOT be here!!
    Discriminator (nvarchar(128)) --Neither should this!!

As you can see, it is including the derived classes as a possible part of the model and/or database system, despite NOTHING in the model having ANYTHING to do with them. THEY reference stuff in the model, NOT the other way around--EVER. I DON'T want it to use them! How do I keep it from doing this?

2
  • Have you considered using composition rather than inheritance? Commented Mar 11, 2015 at 1:44
  • You can add NotMapped properties, instead of creating a new class:) Commented Mar 11, 2015 at 7:47

1 Answer 1

5

Entity framework is doing what it should do here as your setup follows the Table-Per-Hierarchy (TPH) Inheritance pattern.

Discriminator is added so that database can distinguish when a ClassA or a DervivedClassA is added to the DB

You can stop EF mapping your Derived classes using NotMapped attribute. add the following namespace

using System.ComponentModel.DataAnnotations.Schema;

DerivedClassB

[NotMapped]
public class DerivedClassB : ClassB
{
    string SecondBVal { get; set; }
    //Conversion functions similar to those in DerivedClassA go here...
}
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome! Exactly what I wanted. The only problem left is that it isn't COMPLETELY ignoring the derived classes. When I try to give them the same name (diff namespace still) EF complains about them having the same simple name. I AM using EF 6.x, for which they SAY that error was fixed. I guess that claim is false.
That cleans the DB but now I can't insert the derived class objects into the DB
I added the [NotMapped] attribute to my "DerivedClassB", but I still get the error: Mapping and metadata information could not be found for EntityType 'MyNamespace.DerivedClassB'. :-(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.