实体框架代码优先TPC继承自引用子类 [英] Entity Framework Code First TPC Inheritance Self-Referencing Child Class

查看:83
本文介绍了实体框架代码优先TPC继承自引用子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用自引用子类的实体框架和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

问题在于实体框架将外键(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",这是不好的(但不是必须的)./p>

此解决方案"的问题是,当我添加下面的代码以获取更多的类定义时,出现的不是"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

是否可以解决此问题,以便将外键关系设置为用户"表(类)而不是"BaseObject"表?

我尝试使用以下Fluent API,但结果是相同的:

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

解决方案

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

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

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)

解决方案

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.

这篇关于实体框架代码优先TPC继承自引用子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆