2012-01-08 12 views
2

エンティティフレームワークと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 

問題は、Entity Frameworkは「BaseClassのために作成されたテーブルへの外部キー(FK)の関係を設定していることです"であり、" 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 

外部キーの関係は、「ユーザー」テーブル(クラス)へ、そしてない「BaseObject」テーブルに設定されているように、この問題を解決する方法はありますか?

私は以下の流暢APIを試してみましたが、結果は同じです。

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

答えて

0

私はあなたがTPC継承の基底クラスとの関係を使用することができるとは思いません。それは意味をなさないし、IMHOは動作しません。関係は他の有効な関係=参照制約と外部キーとしてデータベース内に表現されなければなりません。データベースは既存のテーブルとの関係をどのように管理すべきですか? TPCとは、親エンティティのすべての内容がすべての子エンティティのテーブルにマップされるため、親エンティティの自己参照関係をモデル化できないため、親エンティティのテーブルが存在しないことを意味します。これは、派生した実体から他の派生した実体すべてにFKの特別なセットをもたらすでしょう。 EFはそれを処理する方法を知らないので、失敗します。

デザインを変更するか、TPT継承を使用する必要があります。

+0

私はTPCの概念を完全に理解しています。私は「BaseClass」のテーブルを必要としません。 BaseClassのポイントは、すべてのクラスの共通基盤を持つことです。そして、すべてのクラスに共通することの1つは、オブジェクトを変更した人(modUser)を保存したいということです。 Entity FrameworkにBaseClass用のテーブルを作成させないようにする方法はありますか? – Thomas

+0

私は答えを受け入れるように私のデザインを変更しました。 – Thomas