Search code examples
c#entity-frameworktable-per-hierarchy

C#, Entity framework, TPH


I have a problem with a TPH mapping. Here are the classes :

Abstract service (base class)

[Table("Services")]
public abstract class AbstractService : IAuditedObject
{
    public int Id { get; set; }

    [DisplayName("Receiver Site")]
    public int? TargetSiteId { get; set; }
    [DisplayName("Receiver Site")]
    public virtual Site TargetSite { get; set; }

    [DisplayName("Start Date")]
    public PartialDate StartDate { get; set; }
    [DisplayName("End Date")]
    public PartialDate EndDate { get; set; }

    [DisplayName("Study")]
    public int? StudyId { get; set; }
    [DisplayName("Study")]
    public virtual Study Study { get; set; }
}

Concrete services

public class AssociatedStaffService : AbstractService
{
    [DisplayName("Person")]
    [Required]
    public int? SourcePersonId { get; set; }
    [DisplayName("Person")]
    public virtual Person SourcePerson { get; set; }

    [DisplayName("Service")]
    [Required]
    public int? RoleId { get; set; }
    [DisplayName("Service")]
    public virtual AssociatedStaffServiceCLI Role { get; set; }

    [DisplayName("Department")]
    public string Department { get; set; }

    public bool IsActive()
    {
        return this.SourcePerson != null && this.TargetSite != null && this.SourcePerson.IsActive() && this.TargetSite.IsActive() && this.Study != null && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
    }
}

public class EthicCommitteeService : AbstractService
{
    [DisplayName("Site")]
    [Required]
    public int? SourceSiteId { get; set; }
    [DisplayName("Site")]
    public virtual Site SourceSite { get; set; }

    [DisplayName("Central")]
    public bool? IsCentral { get; set; }

    public bool IsActive()
    {
        return this.Study != null && this.TargetSite != null && this.SourceSite != null && this.TargetSite.IsActive() && this.SourceSite.IsActive() && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
    }
}

public class ParticipatingService : AbstractService
{
    public const string AUTHORIZATION_DATE = "AuthorizationDate";
    public const string IS_NATIONAL_COORDINATOR = "IsNationalCoordinator";

    [DisplayName("Person")]
    [Required]
    public int? SourcePersonId { get; set; }
    [DisplayName("Person")]
    public virtual Person SourcePerson { get; set; }

    [DisplayName("Service")]
    [Required]
    public int? RoleId { get; set; }
    [DisplayName("Service")]
    public virtual ParticipatingServiceCLI Role { get; set; }

    [DisplayName("Department")]
    public string Department { get; set; }

    public int? RegInvestigatorFormId { get; set; }
    public PartialDate AuthorizationDate { get; set; }
    public bool? IsNationalCoordinator { get; set; }

    public bool IsActive()
    {
        return this.SourcePerson != null && this.TargetSite != null && this.SourcePerson.IsActive() && this.TargetSite.IsActive() && this.Study != null && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
    }
}

public class ExternalService : AbstractService
{
    [DisplayName("Person")]
    [Required]
    public int? SourcePersonId { get; set; }
    [DisplayName("Person")]
    public virtual Person SourcePerson { get; set; }

    [DisplayName("Service")]
    [Required]
    public int RoleId { get; set; }
    [DisplayName("Service")]
    public virtual ExternalServiceCLI Role { get; set; }

    [DisplayName("Department")]
    public string Department { get; set; }

    public bool IsActive()
    {
        return this.SourcePerson != null && this.TargetSite != null && this.SourcePerson.IsActive() && this.TargetSite.IsActive() && this.Study != null && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
    }
}

public class StudyTeamService : AbstractService
{
    [DisplayName("Person")]
    [Required]
    public int? SourcePersonId { get; set; }
    [DisplayName("Person")]
    public virtual Person SourcePerson { get; set; }

    [DisplayName("Service")]
    [Required]
    public int? RoleId { get; set; }
    [DisplayName("Service")]
    public virtual StudyTeamServiceCLI Role { get; set; }

    [DisplayName("Department")]
    public string Department { get; set; }

    public bool IsActive()
    {
        return this.SourcePerson != null && this.TargetSite != null && this.SourcePerson.IsActive() && this.TargetSite.IsActive() && this.Study != null && (this.EndDate == null || this.EndDate.Date == null || this.EndDate.Date > DateTime.Now);
    }
}

I always get the following error :

--- ERROR: One or more validation errors were detected during model generation:

    System.Data.Edm.EdmProperty: Name: Each property name in a type must be unique. Property name 'StartDate' is already defined.
    System.Data.Edm.EdmProperty: Name: Each property name in a type must be unique. Property name 'EndDate' is already defined.  ---

And here is the stack trace :

Unhandled Exception: System.Data.Entity.ModelConfiguration.ModelValidationExcept ion: One or more validation errors were detected during model generation:

    System.Data.Edm.EdmProperty: Name: Each property name in a type must be unique. Property name 'StartDate' is already defined.
    System.Data.Edm.EdmProperty: Name: Each property name in a type must be unique. Property name 'EndDate' is already defined.

at Prisma.Loader.PrismaLoader.Init() in C:\Projects_PrismaLoader\Prisma.Load er\PrismaLoader.cs:line 95 at Prisma.Loader.PrismaLoader.Load(Boolean quick) in C:\Projects_PrismaLoade r\Prisma.Loader\PrismaLoader.cs:line 32 at Prisma.Loader.Program.Main(String[] args) in C:\Projects_PrismaLoader\Pri sma.Loader\Program.cs:line 113

Stack trace is not really useful in this case (it seems...)

Does anyone has an idea where I've made a mistake ? I've been searching for a day now...


Solution

  • Resolved

    It seems that the problem was the PartialDate class. It has to be annotated with the [ComplexType] annotation.