问题
I have a problem With Entity Framework and TPC Inheritance With Self-Referencing Child Class.
My Class definitions:
Public Class BaseObject
<Key()>
<DatabaseGenerated(DatabaseGeneratedOption.None)>
Public Overridable Property iId As Integer
<Required()>
Public Property iModUserId As Integer
<ForeignKey("iModUserId")>
Public Property ModUser As User
<Required()>
Public Property dtModDate As DateTime
End Class
Public Class User
Inherits BaseObject
<Required()>
Public Property sFirstName As String
<Required()>
Public Property sLastName As String
End Class
This is my Context
Public Class DBTestContext
Inherits DbContext
Public Property BaseObjects As DbSet(Of BaseObject)
Protected Overrides Sub OnModelCreating(modelBuilder As System.Data.Entity.DbModelBuilder)
modelBuilder.Entity(Of User)().Map(Sub(m)
m.MapInheritedProperties()
m.ToTable("tUsers")
End Sub)
End Sub
End Class
The problem is that Entity Framework sets the Foreign Key (FK) relationship to the table that is created for the "BaseClass", and NOT to the table created for the "User" class.
This is a major problem since nothing is supposed to be inserted to the "BaseClass" table, and therefore the foreign key constraint is violated when I insert a new user:
Dim context As DBTestContext = New DBTestContext()
Dim user1 As User = New User()
user1.iId = 1
user1.iModUserId = 1
user1.dtModDate = DateTime.Now
context.Users.Add(user1)
context.SaveChanges() 'Error occurs here.
The code works perfectly if I remove the inheritance. The code also work if I remove the DBSer for "BaseObject" and then no table is created for BaseObject, wich is good, but then I cannot easily do a search for all "BaseObjects", wich is bad (but not essential).
The problem with this "solution" is that when I add the code below for more class definitions than the a table for the "BaseObject" class reappears (do not know why, can somebody explain?) and the foreign key relationship is once again set to the "BaseObject" table.
Public Class BaseObject
<Key()>
<DatabaseGenerated(DatabaseGeneratedOption.None)>
Public Overridable Property iId As Integer
<Required()>
Public Property iModUserId As Integer
<ForeignKey("iModUserId")>
Public Property ModUser As User
<Required()>
Public Property dtModDate As DateTime
<InverseProperty("BaseObjects")>
Public Overridable Property Group As ICollection(Of Group)
End Class
Public Class User
Inherits BaseObject
<Required()>
Public Property sFirstName As String
<Required()>
Public Property sLastName As String
End Class
<Table("tGroups")>
Public Class Group
Inherits BaseObject
<InverseProperty("Groups")>
Public Overridable Property BaseObjects As ICollection(Of BaseObject)
End Class
Is there any way to fix this so that the foreign key relationship is set to the "User" table (Class), and not to the "BaseObject" table?
I have tried with the below Fluent API, but the result is the same:
modelBuilder.Entity(Of User)().HasRequired(Function(u) u.ModUser).WithMany().HasForeignKey(Function(u) u.iModUserId)
回答1:
I don't think you can use relation to base class of TPC inheritance. It doesn't make sense and IMHO it cannot work. The relationship must be expressed in database as any other valid relationship = referential constraint and foreign key. How should database manage relation with non existing table? TPC means that there should not be any table for parent entity because whole content of the parent entity is mapped to the table for every child entity so self referencing relation to parent entity cannot be modeled. It would lead to special set of FKs from derived entity to all other derived entities. Because EF doesn't know how to handle it, it fails.
I expect you must either change your design or use TPT inheritance.
来源:https://stackoverflow.com/questions/8781707/entity-framework-code-first-tpc-inheritance-self-referencing-child-class