1

私はDBの最初の方法であるEF 4.1とDbContext POCOコード生成を使用しています。

私のデータベースには、以下に示すように多対多の関係があります。

従業員

従業員ID

従業員名

アカウント

アカウントID

アカウント名

従業員アカウント

従業員ID

アカウントID

問題は、従業員を更新しようとしているときに発生し、アカウントの割り当てを既存のアカウントに変更するため、基本的には以下のようにしています。

using(context)
{
  var query = from e in context.Employees.Include(f => f.Accounts)
              where e.EmployeeId == employeeId
              select;

  Employee emp = query.FirstOrDefault()
}

emp.EmployeeName = "Test";

emp.Accounts.Clear();

Account act = MethodThatLooksUpAccountByName("SomeAccountName");

emp.Accounts.Add(act);

using(context)
{
  context.Accounts.Attach(act);

  emp.State = EntityState.Modified;

  context.Employees.Attach(emp);

  context.SaveChanges();
}

生成されている SQL は、[Employee] テーブルで更新を実行しています。[EmployeeAccount] には何も実行されていません。削除も挿入もありません。

4

1 に答える 1

1

(少なくとも) 最後のAttach. Modifiedアタッチされたシナリオ (DB から読み込まれる) にいるため、状態を に設定する必要もありません。またemp、変更の追跡は何が変更されたかを認識します。

var query = from e in context.Employees.Include(f => f.Accounts)
            where e.EmployeeId == employeeId
            select;
Employee emp = query.FirstOrDefault()

emp.EmployeeName = "Test";
emp.Accounts.Clear();

Account act = MethodThatLooksUpAccountByName("SomeAccountName");
// next line is only necessary if MethodThatLooksUpAccountByName
// uses another context. If it uses the same context you can remove this line.
context.Accounts.Attach(act); 

emp.Accounts.Add(act);

context.SaveChanges();

これは私の意見ではうまくいくはずです。

質問のコードを変更した後に編集します。

2 番目のコンテキストは、独自の変更追跡を実行します。そのため、アカウントを削除して新しいアカウントを追加したことを認識しません。次のように動作するはずです。

using(...context...)
{
    var query = from e in context.Employees.Include(f => f.Accounts)
                where e.EmployeeId == employeeId
                select;

    Employee emp = query.FirstOrDefault()
}

Account act = MethodThatLooksUpAccountByName("SomeAccountName");

using(...context...)
{
    context.Employees.Attach(emp);
    context.Accounts.Attach(act);

    emp.EmployeeName = "Test";
    emp.Accounts.Clear();
    emp.Accounts.Add(act);

    context.SaveChanges();
}

私は感じています、それはあなたが望むものではありません。最後のコンテキストから切り離された状態で、従業員の変更 (古いアカウントの消去と新しいアカウントの追加) を行いましたか? 多対多コレクションの問題は、古いコレクションをクリアまたは変更するコンテキストでロードまたはアタッチする必要があることです。Accountスカラー プロパティを設定したり、エンティティに状態を設定したりして、リンク テーブルで DELETE または INSERT ステートメントをトリガーする方法はありません。コレクション内の変更が検出された場合にのみ、EF によってリンク テーブルが更新されます。

于 2011-10-13T19:15:41.880 に答える