Search code examples
c#entity-framework-6ef-code-first

One class per navigation property


I am trying to add EF6.4 to an existing code base (and removing NHibernate). One of the tables is referenced by multiple other tables.

I have used Entity Framework 6.4 to reverse engineer classes for me (code-first style, with no designer).

For this particular table it produces code like this:

[Table("MyTable")]
public partial class MyTable
{
    public Guid Id { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }

    // Navigation properties
    public virtual TypeA A { get; set; }
    public virtual TypeB B { get; set; }
    public virtual TypeC C { get; set; }
}

I would rather (to match existing NHibernate code) have MyTable be 3 classes with 1 navigation property each (MyTableA, MyTableB, MyTableC):

[Table("MyTable")]
public partial class MyTableA
{
    public Guid Id { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }

    // Navigation properties
    public virtual TypeA A { get; set; }
}

[Table("MyTable")]
public partial class MyTableB
{
    public Guid Id { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }

    // Navigation properties
    public virtual TypeB B { get; set; }
}

[Table("MyTable")]
public partial class MyTableC
{
    public Guid Id { get; set; }
    public string Field1 { get; set; }
    public string Field2 { get; set; }

    // Navigation properties
    public virtual TypeC C { get; set; }
}

How can I accomplish this? (Having the fields in a base class is perfectly ok). I can not change the database for this.


Solution

  • As i know entity framework does not have possibility in dataContext add 3 classes as one table.But you can make projection to three classes.So your code will looks like

    [Table("MyTable")]
    public partial class MyTable
    {
        public Guid Id { get; set; }
        public string Field1 { get; set; }
        public string Field2 { get; set; }
    
        // Navigation properties
        public virtual TypeA A { get; set; }
        public virtual TypeB B { get; set; }
        public virtual TypeC C { get; set; }
    }
    

    so your db context class should have property

    public MyDbContext: : DbContext
    {
        public virtual DbSet<MyTable> MyTable{ get; set; }
    }
    

    than you can add your projection classes

    public class BaseTable
    {
        public Guid Id { get; set; }
        public string Field1 { get; set; }
        public string Field2 { get; set; }
    }
    
    public class MyTableA: BaseTable
    {
        // Navigation properties
        public virtual TypeA A { get; set; }
    }
    

    Than you can add base query projection in your repository

       public class MyTableRepository 
            {
              private IQueryable<MyTableA> tableAEntities;
              public MyTableRepository(MyDbContext  dbContext) 
              {
                  tableAEntities = dbContext.MyTable.Select(t => 
                     new MyTableA 
                    {
                     Id = t.Id, 
                     Field1 = t.Field1, 
                     Field2 = t.Field2, 
                     A = t.A 
                    });
              }
            }