2012-04-30 16 views
6

Entity Framework 4.3 Code Firstを使用しています。多対多リレーションシップの更新に問題があります。Entity Frameworkの多対多リレーションシップを更新できません

私は、次のクラス定義された:

public abstract class Entity 
{ 
    [Column(Order = 0)] 
    [Key] 
    public int Id { get; set; } 

    [Timestamp] 
    [Column(Order = 1)] 
    public byte[] Version { get; set; } 
} 


public class Video : Entity 
{ 
    public string Title { get; set; } 
    public string Description { get; set; } 
    public TimeSpan Length { get; set; } 

    public virtual ICollection<Coworker> Coworkers { get; set; } 
} 


public class Coworker : Entity 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public virtual ICollection<Video> Videos { get; set; } 
} 

データベースが作成されると、スキーマは右を見て: ビデオ、同僚やVideoCoworkersテーブルがあまりにもあり、

せずに私は、リポジトリのパターンを使用しますデータベースにアクセスするためのN層アプリケーションは、私の挿入および更新方法は、次のようになります。私は、エンティティを更新すると

public T Insert(T entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     session.Context.Set<T>().Add(entity); 
    } 
} 

public T Update(T entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     entity = session.Context.Set<T>().Attach(entity); 
     session.Context.Entry(entity).State = EntityState.Modified; 
    } 
    return entity; 
} 

、私はCRエンティティオブジェクトをDTOから削除する必要があります。そのため、DbSet.Attachを選択してプロパティを1つずつ更新するのではなく、その代わりに使用します。

私は、データベースを初期化すると、私はいくつかのテストデータを追加します。

  1. は、私が最初と最後の名前を設定する3人の同僚を作成します。 (A、B、C)
  2. 3つのビデオを作成し、タイトル、説明、長さを設定し、同僚を設定します。最初のビデオにはA、B、2番目にB、C、3番目にA、Cがあります。

私はコードからビデオを一覧表示するとき、私はVideo.Coworkersコレクションは良好な値で満たされていることがわかります、と私はSQL Server Management Studioで(VideoCoworkers)リンクテーブルを照会するとき、それはまた、よさそうです。

私の問題は たとえばビデオのタイトルを更新すると動作します。しかし、既存の同僚(BとC)をVideo2から削除しようとすると、同僚Aを追加しようとすると、関係は更新されません。また、私は新しい同僚を追加しようとするとき、または削除しようとするときにのみ機能しません。私は、Update()メソッドのパラメータとして使用されるエンティティを作成します。これは、新しいVideoエンティティを、Find()メソッドを使用してIdからデータベースから選択された新しい同僚のコレクションで作成することによって作成されます。

多対多リレーションシップを更新する正しい方法は何ですか?

+0

あなたはビデオから同僚をどのように削除するかは分かりませんが、ビデオの同僚のコレクションをループして、削除したDTOに一致するアイテムをマークする必要があります。 –

答えて

-1

データベースを最初にasp.net mvcにマスター詳細を保存する方法については、hereを参照してください。うまくいけば、最初にコードについてのアイデアが得られることを願っています。またknokout.js

+0

あなたのコメントをありがとうが、これらのリンクは私の更新の問題を解決するのに役立たなかった。 – mrtx

+0

これを参照してくださいhttp://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ – Tassadaque

+0

あなたのコメントをお寄せいただきありがとうございますが、私の問題はデータアクセス層、そのMVCもJSも関係しません。実際に私はWebFormsとWinFormsを使用していますが、転送された各DTOは両方の方法で正しく見えます。そのため、アプリケーションのクライアント側とは何の関係もありません。 – mrtx

6

を見ているかもしれませんが、私はビデオ2既存の同僚(BおよびC)、 から削除して、同僚Aを追加しようとしようとすると、その関係は更新されません。重要な部分は、あなたがすなわち子供を削除し、追加し、エンティティを変更、元の状態にエンティティをロードするか、または添付しなければならないということである

using (var session = new DatabaseSession()) 
{ 
    video2 = session.Context.Set<Video>().Include(v => v.Coworkers) 
     .Single(v => v.Id == video2Id); 

    coworkerA = new Coworker { Id = coworkerAId }; 
    session.Context.Set<Coworker>().Attach(coworkerA); 

    video2.Coworkers.Clear(); 
    video2.Coworkers.Add(coworkerA) 

    session.Context.SaveChanges(); 
} 

:正しい手順は次のようになり、一般的なリポジトリを使用せずに

、変更を保存します。 EFの変更検出により、リンクテーブルのエントリに必要なINSERT文とDELETE文が作成されます。状態をModifiedの一般的なUpdateメソッドに設定する簡単な手順は、ビデオタイトルの変更などのスカラープロパティの更新にのみ適していますが、エンティティ間の関係の更新には使用できません。

2

のために、この問題を解決:

  1. は、コレクション(コレクションは、ロードされているためされていない)
  2. 変更の保存変更
  3. への変更エンティティの状態をコンテキスト
  4. 負荷にエンティティをアタッチ

更新コードは次のようになります。

public Video Update(Video entity) 
{ 
    //Creates database context. When it disposes, it calls context.SaveChanges() 
    using (var session = new DatabaseSession()) 
    { 
     entity = session.Context.Set<Video>().Attach(entity); 
     session.Context.Entry(entity).Collection(p => p.Coworkers).Load(); 
     session.Context.Entry(entity).State = EntityState.Modified; 
    } 
    return entity; 
} 
関連する問題