2016-12-26 9 views
0

EFで以下の関係を設定する方法がわかりません。エンティティフレームワークのモデリングと1対多の関係

言語辞書モデルを作成する必要があるとします。私は1つの言語と別の言語でアイテム(単語など)を持っています。これら2つの項目の間には何らかの関係がある。例えば

:「フント」(ドイツ語) - >「犬」(英語)、関係型は

public enum Language 
{ 
    English, 
    German, 
} 

public class Item 
{ 
    public long ID { get; set; } 
    [Required] 
    public string Value { get; set; } 
    [Required] 
    public Language Language { get; set; } 

    public virtual ICollection<ItemRelation> ItemRelations { get; set; } 
} 

public enum ItemRelationType 
{ 
    Translate, 
    Synonym, 
} 

public class ItemRelation 
{ 
    public long ID { get; set; } 

    [ForeignKey("ItemID")] 
    public Item Item { get; set; } 

    [ForeignKey("RelativeItemID")] 
    public Item RelativeItem { get; set; } 

    [Required] 
    public ItemRelationType Type { get; set; } 
} 

EF標準移行が1の場合には、いくつかのエラーを投げるか、列またはFKS Iを作成し、「翻訳」でありますもう片方には(Item_IDなど)しないでください。

、私はいくつかの流暢なAPIを構成する必要があると思います - しかし、私は私はあなたがこれで逃げることができるかもしれないどのように考えるか...

+0

「いくつかの言語辞書モデル」、「いくつかの「関係」、「何らかの誤り」、「1つの場合 - 他の場合」 - これはすべてあいまいです。 –

答えて

1

あなたは、実際のFKフィールドItemIDRelativeItemID表示されません。

public class ItemRelation 
{ 
    public long ID { get; set; } 

    public long ItemID { get; set; } // Missing 
    [ForeignKey("ItemID")] 
    [InverseProperty("ItemRelations")] 
    public virtual Item Item { get; set; } 

    public long RelativeItemID { get; set; } // Missing 
    [ForeignKey("RelativeItemID")] 
    [InverseProperty("RelativeItemRelations")] 
    public virtual Item RelativeItem { get; set; } 

    [Required] 
    public ItemRelationType Type { get; set; } 
} 

上記宣言はvirtualように遅延ロードの動作を使用します。それは必要ではなく、あなたはそれを削除することができます。その結果、怠惰な読み込みはうまくいきません。これは大丈夫です。

public class Item 
{ 
... 
    public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; } 
... 
} 

そして、あなたのコンテキストクラスには、まだいない場合は、OnModelCreatingをオーバーライドすることにより、カスケード削除規則を無効にする:あなたはプロパティを追加する必要がある第2の関係のためのナビゲーションプロパティをしたいと仮定すると、

次のように:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
... 
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
... 

このソリューションは、動作するはずですが、効果的カスケードは、多くの関係に、すべて1に削除無効化されます。アップサイドは、流暢なAPIを使用して、ケースバイケースで戻すことができるということです。あなたが望むものを達成するために

第二の方法は、次のようにちょうど流暢なAPIを使用することです:

は、あなたのItemエンティティに第2のナビゲーションプロパティを追加します。

public class Item 
{ 
... 
    public virtual ICollection<ItemRelation> RelativeItemRelations { get; set; } 
... 
} 

ItemRelationエンティティは、FKSが欠落しています、だからここにある:

パブリッククラスItemRelation { public long ID {get;セット; }

public long ItemID { get; set; } // Missing 
    public virtual Item Item { get; set; } 

    public long RelativeItemID { get; set; } // Missing 
    public virtual Item RelativeItem { get; set; } 

    [Required] 
    public ItemRelationType Type { get; set; } 
} 

とナビゲーションプロパティを設定するには、カスケーディングの問題を回避するには、あなただけの流暢APIを使用して関係を定義します。

public TheContext : DbContext 
{ 
    public DbSet<Item> Items { get; set; } 
    public DbSet<ItemRelation> ItemRelations { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<ItemRelation>() 
       .HasRequired(e => e.Item) 
       .WithMany(t => t.ItemRelations) 
       .HasForeignKey(e => e.ItemID) 
       .WillCascadeOnDelete(false); 

     modelBuilder.Entity<ItemRelation>() 
       .HasRequired(e => e.RelatedItem) 
       .WithMany(t => t.RelativeItemRelations) 
       .HasForeignKey(e => e.RelativeItemID) 
       .WillCascadeOnDelete(false);  


     // Uncomment the following if you want to disable all cascading deletes and automatic fk creation conventions 
     // modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>(); 
     // modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
     // modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 

    ... 
    } 
} 

Read here for an opinion on why you might consider disabling those conventions.

+0

はい。しかし、このように私は次のエラーがあります: "FOREIGN KEY制約を導入すると、 'ItemRelations'テーブルのFK_dbo.ItemRelations_dbo.Items_RelativeItemIDが循環または複数のカスケードパスを引き起こす可能性があります。 制約またはインデックスを作成できませんでした。以前のエラーを参照してください。多分私はcascadeDeleteをfalseに設定する必要があります - 私はこのプロパティをよく知らないです。 – Petr

+0

@Petrカスケード削除を無効にする方法と、流暢なAPIを使用して関係を構成する方法があります。私は答えに両方を加えました。 – Klinger

1

を確認していない:

public class ItemRelation 
{ 

    public long Id { get; set; } 

    [ForeignKey("PrimaryItemId")] 
    public Item Item { get; set; } 
    public long PrimaryItemId { get; set; } 

    [ForeignKey("RelatedItemId")] 
    public Item RelatedItem { get; set; } 
    public long RelatedItemId { get; set; } 

    public ItemRelationType RelationType; 
} 

お知らせこのクラスのこと今度はItemエンティティと2つの関係があり、2つの外部キーが生成されます。各Itemプロパティには[ForeignKey]属性があり、文字列引数はlongを外部キー列として指定しています。

この回答を別のトラックのナッジとして表示します。あなたのユースケースに合っているかどうかを調べるには、このトピックをさらに調べてください。

そして、あなたはEF規則のビットを無効にするとともに、InverseProperty属性を使用することができ、ナビゲーションプロパティを設定する(下図):

関連する問題