6

Entity Framework 4.3 Code First を使用していますが、多対多の関係の更新に問題があります。

次のクラスを定義しました。

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; }
}

データベースが作成されると、スキーマは正しく表示されます。Videos、Coworkers、および VideoCoworkers テーブルもあります。

N 層アプリケーションでリポジトリ パターンを使用してデータベースにアクセスします。Insert および Update メソッドは次のようになります。

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;
}

エンティティを更新するときは、DTO からエンティティ オブジェクトを作成します。そのため、エンティティ オブジェクトを選択してプロパティを 1 つずつ更新するのではなく、DbSet.Attach を使用します。

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

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

コードからビデオを一覧表示すると、Video.Coworkers コレクションが適切な値で満たされていることがわかります。また、SQL Server Management Studio でリンク テーブル (VideoCoworkers) をクエリすると、適切に表示されます。

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

多対多の関係を更新する正しい方法は何ですか?

4

3 に答える 3

6

しかし、Video2 から既存の同僚 (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スカラー プロパティの更新 (ビデオ タイトルの変更など) にのみ適していますが、エンティティ間の関係の更新には機能しません。

于 2012-06-23T11:56:00.553 に答える
-1

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

于 2012-04-30T09:28:55.210 に答える