Entity Framework Code-First セットアップに次のモデル クラスがあるとします。
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Team> Teams { get; set; }
}
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Person> People { get; set; }
}
このコードから作成されたデータベースには、人とチームの間の多対多の関係を表す TeamPersons テーブルが含まれています。
ここで、切断された Person オブジェクト (プロキシではなく、まだコンテキストにアタッチされていない) があり、その Teams コレクションに 1 つ以上の切断された Team オブジェクトが含まれており、そのすべてが既にデータベース内にあるチームを表しているとします。たとえば、ID 1 の Person と ID 3 の Team がデータベースに既に存在する場合、次のようなオブジェクトが作成されます。
var person = new Person
{
Id = 1,
Name = "Bob",
Teams = new HashSet<Team>
{
new Team { Id = 3, Name = "C Team"}
}
};
このオブジェクトを更新して、更新後に TeamPersons テーブルに Bob の 1 つの行が含まれ、彼を C Team にリンクする最善の方法は何ですか? 私は明白なことを試しました:
using (var context = new TestContext())
{
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}
ただし、Teams コレクションはこれによって無視されます。私は他にもさまざまなことを試しましたが、ここで求めていることを正確に行うものは何もないようです. 助けてくれてありがとう。
編集:
したがって、データベースから Person と Team[s] の両方をフェッチし、それらを更新してから変更をコミットできることがわかりました。
using (var context = new TestContext())
{
var dbPerson = context.People.Find(person.Id);
dbPerson.Name = person.Name;
dbPerson.Teams.Clear();
foreach (var id in person.Teams.Select(x => x.Id))
{
var team = context.Teams.Find(id);
dbPerson.Teams.Add(team);
}
context.SaveChanges();
}
ただし、 Person が複雑なエンティティである場合、これは面倒です。Automapper などを使用して物事を少し簡単にできることはわかっていますが、新しいものを取得してすべてのプロパティをコピーするのではなく、元の人物オブジェクトを保存する方法がない場合は残念です...