To summarize my model:
- License and Certificate are children of Qualification
- A Qualification has one and only one Profession
- A Profession is either a licensed kind (type 1) or a certified kind (type 2)
Requirement: Represent the relationships between business entities without introducing redundancy into database schema. Type of Qualification (license/certificate) must match type of Profession.
Here is my simplified model as it currently stands -- I explain why this doesn't work below:
Public Class Profession
<Key()>
<DataMember(Order:=0)>
Public Property Type As Integer
<Key()>
<DataMember(Order:=1)>
Public Property Code As String
Public Property Title As String
End Class
Public Class Qualification
Public Property Id As Integer
Public Property PersonId As Integer
Public Property Type As Integer
Public Property ProfessionCode As String
Public Overridable Property Person As Person
Public Overridable Property Profession As Profession
End Class
Public Class License
Inherits Qualification
Public Property Number As String
End Class
Public Class Certificate
Inherits Qualification
Public Property IssuerName As String
End Class
Here's the simplified ModelBuilder:
modelBuilder.Entity(Of Qualification) _
.Property(Function(q) q.ProfessionCode).IsRequired()
modelBuilder.Entity(Of Qualification) _
.HasRequired(Of Profession)(Function(q) q.Profession) _
.HasConstraint(Function(q, p) p.Type = q.Type AndAlso p.Code = q.ProfessionCode)
modelBuilder.Entity(Of Qualification) _
.MapHierarchy() _
.Case(Of Qualification)(Function(q) New With {
q.Id,
q.PersonId,
q.ProfessionCode,
.Type = 0) _
.Case(Of License)(Function(q) New With {
q.Number,
.Type = 1}) _
.Case(Of Certificate)(Function(q) New With {
q.IssuerName,
.Type = 2}) _
.ToTable("dbo.Qualifications")
The reason this doesn't work is that EF4 does not allow FK properties to double as a TPH discriminator. This means Type cannot be both a discriminator and a foreign key field. Trying to hard-code Profession Type in the HasConstraint method for each entity also doesn't work -- this generates an exception.
A possible solution would be to add a surrogate key to Profession, get rid of Type property in Qualification and replace it with ProfessionId FK. This would remove the redundancy concern, but also destroy TPH. In effect, the discriminator moves from Qualification to Profession. The problem here is that I haven't figured out a way to map License and Certificate objects. Maybe I can map to views instead? But how do I do that in Code First?
So, now I am faced with a number of unsavory choices. Any suggestions?