2017-09-19 1 views
1

命名規則と理解の組み合わせでは苦労しているようです。多対多の関係を完全にコードもデータベースも更新しない

私はデータベースを継承しており、MVCサイトを構築していて、「データベースファースト」のワークフローをうまくプレイすることができませんでした。最後に、私は手動でコンテキストクラスを構築し、幸せに働いています。

私は現在、いくつかの他の既存のエンティティ(多対多)に関係のあるエンティティを追加できない状況にあります。このような

マイデータベースルックス(この質問のために簡略化):

ListItem  Option  OptionListItems 
======  ======  =============== 
Id   Id   ListItem_Id 
Name   Name   Option_Id 

私の状況は私が私のListItemの全てを取得することができますプロパティが含まれています

public virtual DbSet<ListItem> ListItems { get; set; } 

そして、私はいくつかを使用する場合LINQ、私は以下のようなことをして、アイテムが返され、多対多の関係が満たされ、私のListItemの中にOptionのリストが得られます:

var item = _context.ListItems 
.Where(p => p.Id == id) 
.Include(p => p.Options) 
.SingleOrDefault(); 

実際には、上記のクエリを実行しようとしたときに手動でデータベース内にクロスリファレンステーブルを作成しなければならなかった。例外は、dbo.OptionListItemsというオブジェクトがないと言われた。だから、私たちはすべてがいいと思った。

は今、私は新しいListItemを作成して、1つまたは複数既存Optionにリンクする必要があると私は途方に暮れてよ。

私は単独で私の新しいListItemを作成し、それが失敗したlistItem.Options.Add(...)を呼び出そうと、私は特定のOptionへの参照を取得し、option.ListItems.Add(...)をしようとしようとした場合、私もまったく同じ例外を取得したら。

エラーが一種の愉快であり、私が持っているものとは反対側のテーブル名です:

{"Invalid object name 'dbo.ListItemOptions'."} 

私はそれが直接に私の文脈上のタイプとプロパティを構築するためにEFの穀物に反すると思われます

public virtual DbSet<OptionListItem> OptionListItems { get; set; } 

しかし、私は新しい関係を作成するパターンに完全に困惑しています。

+0

あなたがコントロールする必要がある場合は、DB最初のものを引き裂いたが、コードファーストでどのようにわからない多対多あなたは[この]のように流暢なマップコードが必要になります(http://www.entityframeworktutorial .net/code-first/configure-many-many-relationship-in-code-first.aspx)(一番下に近い) –

+0

ええ、それは変です。私はDBと手作業で作成したPOCOをいくつか持っていました。その上に足場や移動に頼るのではなく、手作業で両面にビットを追加しました。 マッピングを作成しようとする前に(私はそのポストを見ましたが、それが最良のアプローチであるとは確信できませんでした)、使いやすいパターンは何ですか?私は 'ListItem'と' .Add'をOptionsコレクションに持っていくので、それがうまくいくはずです。 – Neil

答えて

0

私たちはこれを(多対多)宣言的に動作させています。擬似コード:

public class ListItem 
{ 

    public ListItem() 
    { 
     this.RelatedOptions = new HashSet<OptionListItems>(); 
    } 

    [Key] 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<OptionListItems> RelatedOptions {get; set;} 
} 

public class Option 
{ 
    public Ortion() 
    { 
     this.RelatedItems = new HashSet<OptionListItems>(); 
    } 

    [Key] 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public virtual ICollection<OptionListItems> RelatedItems {get; set;} 
} 


public class OptionListItems 
{ 
    [Key] 
    public int Id {get; set;} 

    [Column("ListItemId", Order = 1)] 
    [ForeignKey("ParentListItem")] 
    public int ListItemId {get; set;} 

    [Column("OptionId", Order = 2)] 
    [ForeignKey("ParentOption")] 
    public int OptionId {get; set;} 

    public virtual ListItem ParentListItem {get; set;} 
    public virtual Option ParentOption {get; set;} 
} 

これは宣言

+0

ありがとう - 私はすでに非常によく似たモデルを持っていましたが、少なくともこの投稿は私がそれを検証するのを助けました。 – Neil

0

クレジットが正しい方向に私を指しているため、スティーブ・グリーンに行くの完全な関係を作成する必要があります。 私が持っていたテーブルはコンベンションで作成されましたが、を.Include(p => p.Options)と照会したときに働いていましたが、アップデートをしようとすると規約が破綻するようです。なぜ私は不明ですが、クエリテーブルの構築は<Entity1>+<Entity2>+sだと思われますが、更新するときは<Entity2>+<Entity1>+s ...

fluentAPIを使用して、エンティティ間の特定のマッピングを作成し、相互参照テーブルとクエリと更新の両方の作業を強制しました。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<ListItem>() 
      .HasMany<Option>(s => s.Options) 
      .WithMany(c => c.ListItems) 
      .Map(cs => 
      { 
       cs.MapLeftKey("ListItem_Id"); 
       cs.MapRightKey("Option_Id"); 
       cs.ToTable("OptionListItems"); 
      }); 
    }