views:

189

answers:

1

Hi all,

I've got the following model and I want ShiftRequest and MissionRequest to have a single table in the DB.

    public class RequestBase
    {
        public int Id { get; set; }
        public DateTime? RequestDate { get; set; }
        public int UserId { get; set; }

        public virtual ICollection<Notification> Notifications { get; set; }

    }

    public class ShiftRequest : RequestBase
    {
        public virtual Column Column { get; set; }

    }

    public class MissionRequest : RequestBase
    {
        public virtual Mission Mission { get; set; }
    }

I've tried to do it in the override void OnModelCreating(ModelBuilder modelBuilder) method but only one RequestBases table is created:

modelBuilder.Entity<ShiftRequest>().MapSingleType().ToTable("dbo.ShiftRequests");
modelBuilder.Entity<MissionRequest>().MapSingleType().ToTable("dbo.MissionRequest");

What am I doing wrong?

EDIT

Column and Mission are also entities in my model, is that acceptable?

+1  A: 

Check the section about TPH in this article. If Mission and Column are complex types you will also find there how to map them. Generally you have to use MapHiearchy and Case methods instead of MapSingleType.

Edit:

Here is the example:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;


namespace EFTest
{
    public class RequestBase
    {
        public int Id { get; set; }
        public DateTime? RequestedDate { get; set; }
        public int UserId { get; set; }
    }

    public class Mission
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<MissionRequest> MissionRequests { get; set; }
    }

    public class Column
    {
        public string Name { get; set; }
    }

    public class MissionRequest : RequestBase
    {
        public virtual Mission Mission { get; set; }
    }

    public class ShiftRequest : RequestBase
    {
        public Column Column { get; set; }
    }

    public class TestContext : DbContext
    {
        public DbSet<RequestBase> Requests { get; set; }
        public DbSet<Mission> Missions { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ContainerName = "EFTest";
            modelBuilder.IncludeMetadataInDatabase = false;

            // Example of complex type mapping. First you have to define 
            // complex type. Than you can access type properties in  
            // MapHiearchy.
            var columnType = modelBuilder.ComplexType<Column>();
            columnType.Property(c => c.Name).HasMaxLength(50);

            modelBuilder.Entity<Mission>()
                .Property(m => m.Id)
                .IsIdentity();

            modelBuilder.Entity<Mission>()
                .HasKey(m => m.Id)
                .MapSingleType(m => new { m.Id, m.Name })
                .ToTable("dbo.Missions");

            modelBuilder.Entity<RequestBase>()
                .Property(r => r.Id)
                .IsIdentity();

            // You map multiple entities to single table. You have to  
            // add some discriminator to differ entity type in the table. 
            modelBuilder.Entity<RequestBase>()
                .HasKey(r => r.Id)
                .MapHierarchy()
                .Case<RequestBase>(r => new { r.Id, r.RequestedDate, r.UserId, Discriminator = 0 })
                .Case<MissionRequest>(m => new { MissionId = m.Mission.Id, Discriminator = 1 })
                .Case<ShiftRequest>(s => new { ColumnName = s.Column.Name, Discriminator = 2 })
                .ToTable("dbo.Requests");
        }
    }
}

Edit 2:

I updated example. Now Mission is entity instead of complex type.

Ladislav Mrnka
@Ladislav Mrnka, do this mean `Mission` and `Column` can't be configured as entities??
CD
Yes they can. I over looked virtual keyword in your properties and I thought it is inner complex type. But you can define them as navigation properties as well.
Ladislav Mrnka
I have midified the example. Now Mission is an entity. You can use same approach for Column.
Ladislav Mrnka
Do you use column in multiple inherited entities?
Ladislav Mrnka