【问题标题】:Entity Framework Code First TPC Inheritance Self-Referencing Child Class实体框架代码优先TPC继承自引用子类
【发布时间】:2012-01-08 21:55:36
【问题描述】:

我在使用自引用子类的实体框架和 TPC 继承方面遇到问题。

我的班级定义:

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

这是我的上下文

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

问题在于 Entity Framework 将外键 (FK) 关系设置为为“BaseClass”创建的表,而不是为“User”类创建的表。

这是一个主要问题,因为不应该向“BaseClass”表中插入任何内容,因此当我插入新用户时违反了外键约束:

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.

如果我删除继承,代码将完美运行。如果我删除“BaseObject”的 DBSer,然后没有为 BaseObject 创建表,该代码也可以工作,这很好,但是我不能轻易地搜索所有“BaseObjects”,这很糟糕(但不是必需的)。

这个“解决方案”的问题在于,当我添加下面的代码以获得更多的类定义时,“BaseObject”类的表重新出现(不知道为什么,有人可以解释一下吗?)并且外键关系是再次设置为“BaseObject”表。

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

有没有办法解决这个问题,以便将外键关系设置为“User”表(类),而不是“BaseObject”表?

我尝试过使用以下 Fluent API,但结果是一样的:

modelBuilder.Entity(Of User)().HasRequired(Function(u) u.ModUser).WithMany().HasForeignKey(Function(u) u.iModUserId)

【问题讨论】:

    标签: entity-framework-4.1 ef-code-first


    【解决方案1】:

    我认为您不能使用与 TPC 继承基类的关系。这没有意义,恕我直言,它无法工作。该关系必须在数据库中表示为任何其他有效关系 = 引用约束和外键。数据库应该如何管理与不存在表的关系? TPC 意味着父实体不应该有任何表,因为父实体的全部内容都映射到每个子实体的表,因此无法对父实体的自引用关系进行建模。这将导致从派生实体到所有其他派生实体的特殊 FK 集。因为 EF 不知道如何处理它,所以它失败了。

    我希望您必须更改您的设计或使用 TPT 继承。

    【讨论】:

    • 我完全理解 TPC 概念,我不想要(或不需要)“BaseClass”表。 BaseClass 的重点是为所有类提供一个共同的基础,所有类的共同点之一是我想存储谁修改了一个对象(即 modUser)。有没有办法强制实体框架不为 BaseClass 创建表?
    猜你喜欢
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多