none
EF5 / VS10 (Model First)- Inherited Entities missing from DbContext - only base class(es) appears. RRS feed

  • Question

  • Hi:

    I'm getting re-acquainted hands-on with EF after a couple of years; here's the basic problem I'm having:

    I created three Entities - (1) Person, which is my base/abstract class, and (2) Doctor and (3) Patient - both of these inherit from the Person Entity.

    When I generate my code, I get all the classes generated by Model1.tt, but the Model1.Context.cs file only has:

    Public DbSet<Person> People { get; set;} 

    and is "missing" the Doctor and Patient entities.

    I was following the basic steps in this tutorial: http://msdn.microsoft.com/en-us/data/jj205424 

    When it comes time to add / delete / enumerate Patients or Doctors, I am stuck as there are no related DbContext Entities for Doctor nor Patient.

    Basic background:

    1. Created new console app, used NuGet to install EF 5.0,
    2. Removed reference to System.Data.Entity and added reference to EntityFramework.dll (appears to be necessary to successfully build EF5 project in VS10)
    3. Created a new data model (using the default model name, i.e. Model1.edmx) and on the design surface, I added Person, Doctor, and Patient entities, then added inheritance for the Doctor and Patient entities.
    4. Generated Database from Model (three tables, as expected)
    5. Right-clicked on Model design surface and chose 'Add Code Generation Item...' , used 'Online Templates' and selected EF 5.x DbContext generator, using default Model1.tt name.
    6. When I tried to implement adding a Patient via basic console test, noticed the Doctor and Patient entities did not exist within DbContext.

    Please advise what am I missing / doing wrong?

    Friday, March 15, 2013 8:35 PM

Answers

  • Doh!

    Actually, it turns out that the code I posted above *does* work.  I'd neglected to regenerate the database from my model after adding the MedicalHistory property. Once I did that, the code completes and the database is updated.  Along the way, I discovered that as an alternative to the dbPeople.Add(newP) is using db.Set<Patient>().Add(newP)  which is longer, but imo more clear.  

    Also of note with that is that the db.Set<T> method can be used to easily reference specific derived classes within the dbContext. 

    Lastly, I believe I should have used 'Derived Entities' instead of 'Inherited Entities' in the title and elsewhere in my earlier posts.  Live and learn...

    • Marked as answer by Jsoar Tuesday, March 19, 2013 6:03 AM
    Tuesday, March 19, 2013 6:02 AM

All replies

  • Hi Jsoar,

    Welcome to the MSDN forum.

    I think you have done nothing wrong. You should be able to find the class definitions under Model.tt after you save the .edmx file. There should be something like Doctor.cs, Patient.cs and Person.cs.

    Good day.


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 18, 2013 5:44 AM
  • Hi Alexander:

    Thanks for your reply - I do see those classes under Model.tt (tried to state that in my original post). But my understanding is that for my CRUD operations, I need to use the DbContext based class (Model1.Context.cs, under Model1.Context.tt).  This class only contains Person (code pasted below).  So while I can indeed use the Patient and Doctor classes in my code there's no way to persist them to the database, load them from the database, etc.

    namespace EFTest_Inheritance
    {
        public partial class EF_InheritanceTestEntities : DbContext
        {
            public EF_InheritanceTestEntities()
                : base("name=EF_InheritanceTestEntities")
            {
            }
        
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                throw new UnintentionalCodeFirstException();
            }
        
            public DbSet<Person> People { get; set; }
        }
    }

    If, for example, I try to add a new Patient (following/adapting the basic tutorial I referenced), it will throw an exception if I try to coerce the 'People' dbSet to add a Patient, because only a new 'Person' can be added - the additional fields of Patient (or Doctor) are not recognized:

      static void Main(string[] args)
            {
                using (var db = new EF_InheritanceTestEntities())
                {
                    // Create and save a new Blog
                    Console.Write("Enter a First Name for a new Patient: ");
                    var nameF = Console.ReadLine();
                    Console.Write("Enter a Lady Name for the new Patient: ");
                    var nameL = Console.ReadLine();
    
                    var newP = new Patient { FirstName = nameF, LastName = nameL };
                    newP.MedicalHistory = "(none)";
                    db.People.Add(newP);
                    db.SaveChanges();
    
                }
            }
    Running the above will throw an exception at the call to db.SaveChanges ( ....InnerException: System.Data.SqlClient.SqlException 
                Message=Invalid column name 'MedicalHistory'.
                Source=.Net SqlClient Data Provider)

    It seems to me like I must be making some very basic mistake... but I'm not understanding what it is.  More generally stated: how do I perform CRUD operations on my Doctor and Patient classes?

     
    • Marked as answer by Jsoar Tuesday, March 19, 2013 6:02 AM
    • Unmarked as answer by Jsoar Tuesday, March 19, 2013 6:03 AM
    Monday, March 18, 2013 6:14 PM
  • Doh!

    Actually, it turns out that the code I posted above *does* work.  I'd neglected to regenerate the database from my model after adding the MedicalHistory property. Once I did that, the code completes and the database is updated.  Along the way, I discovered that as an alternative to the dbPeople.Add(newP) is using db.Set<Patient>().Add(newP)  which is longer, but imo more clear.  

    Also of note with that is that the db.Set<T> method can be used to easily reference specific derived classes within the dbContext. 

    Lastly, I believe I should have used 'Derived Entities' instead of 'Inherited Entities' in the title and elsewhere in my earlier posts.  Live and learn...

    • Marked as answer by Jsoar Tuesday, March 19, 2013 6:03 AM
    Tuesday, March 19, 2013 6:02 AM