0

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...

Whoami
  • 334
  • 4
  • 16
  • Could you tell me what is 'IAuditedObject'? – Likurg Apr 11 '12 at 13:22
  • IAuditedObject is an empty interface that allow us to record every changes done on an object so we can recreate it whenever we want. (= Trailed object) – Whoami Apr 11 '12 at 13:37

2 Answers2

0

I believe you need to make StartDate and EndDate virtual? Edm is trying to override the functionality, but because they are sealed it cannot override them so it is duplicating them in the IL?

Marc Armstrong
  • 266
  • 3
  • 11
  • Seems not, just tried to set them as virtual and still the same error. But thanks for the try :) – Whoami Apr 11 '12 at 13:36
0

Resolved

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

Whoami
  • 334
  • 4
  • 16
  • Hi, how do you implement the services for those entities? You have all operations for every entity or any kind of common use to implement them? – Patrick Jan 06 '13 at 14:56
  • @Patrick What do you mean by services ? If you are talking about the operation that could be done against the database engine, we currently use generic repositories / managers to provide those. – Whoami Jan 08 '13 at 07:10
  • I'm talking about the CRUD operations over a TPH class's relashionship, for example, an Insert, how can I insert the common fields (AbstractService) in the database and the ExternalService fields, without violating the DRY principle? – Patrick Jan 08 '13 at 10:23
  • I'll point you to an other question I asked that explain pretty well the generic repository / managers (with code). THese accept every kind of object. You don't have to care about the AbstractServices properties since this class is abstract. They will be included into the concrete class and put into your database with a single insert of the concrete class (http://stackoverflow.com/questions/10089491/entity-framework-abstract-class-generic-repository-and-generic-manager)... Hope this helps (feel free to ask if you don't understand something in the code examples) – Whoami Jan 10 '13 at 11:31
  • Sorry but it's kinf of hard to understand the code and logic, can you map it with my concrete classes, maybe it gests more easy to understand: http://stackoverflow.com/questions/14174771/tph-approach-service-implementation thank you – Patrick Jan 10 '13 at 15:38