C# 使用多对多关系更新断开连接的实体
假设我在实体框架代码第一次设置中有以下模型类:C# 使用多对多关系更新断开连接的实体,c#,entity-framework,ef-code-first,many-to-many,dbcontext,C#,Entity Framework,Ef Code First,Many To Many,Dbcontext,假设我在实体框架代码第一次设置中有以下模型类: 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 strin
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; }
}
但是团队集合只是被忽略了。我也尝试过其他各种方法,但似乎没有什么能完全满足我的要求。谢谢你的帮助
编辑:
因此,我可以从数据库中获取人员和团队,更新他们,然后提交更改:
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();
}
然而,如果一个人是一个复杂的实体,这是一种痛苦。我知道我可以使用Automapper或其他工具使事情变得更简单,但如果无法保存原始的person对象,这似乎是一种耻辱,一般的方法是从数据库中获取
团队
,并将其添加到人员的团队
集合中,而不必获取一个新的团队并复制所有的属性。设置EntityState.Modified只影响标量属性,而不影响导航属性。尝试先选择现有实体,然后将团队附加到person对象的团队集合
类似这样:(语法可能不完全正确)
这就是EF s**ks的位置。对于断开连接的场景,效率非常低。加载更新/删除和重新附加更新的数据时,不能仅将更新的实体附加到上下文,因为上下文中可能已经存在具有相同键的实体,在这种情况下,EF将抛出。需要做的是检查具有相同密钥的实体是否已经在上下文中,并相应地附加或更新。使用多对多关系子对象更新实体更糟糕。删除已删除的子对象是从子对象的实体集中删除的,而不是从引用属性中删除,这非常混乱。您可以使用“附加”方法。试试这个:
using (var context = new TestContext())
{
context.People.Attach(person);
//i'm not sure if this foreach is necessary, you can try without it to see if it works
foreach (var team in person.Teams)
{
context.Teams.Attach(team);
}
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}
我没有测试这段代码,如果您有任何问题,请告诉我。购买本身,这似乎不起作用:将从db获取的团队添加到非代理的人员仍然不会更新TeamPersons表。工作是从数据库中同时获取团队和人员(因此人员是代理),但是您必须更新此获取的人员以匹配被保存的人员……啊,您是对的(应该读得更好)。编辑后:您可以使用DbContext.Entry(dbPerson).CurrentValues.SetValues(person)
。谢谢,这很有用-我不知道CurrentValues.setValuesHanks,但是我必须从我想要保存的原始人更新这个新人(请参见我的编辑)-我希望有另一种方法。好的,你是说断开连接的person对象有很多更改?可能是的:我想知道从断开连接的person对象更新db的最佳方法,但不知道该对象的哪些属性已更改。
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();
}
using (var context = new TestContext())
{
var person = context.Persons.Where(f => f.Id == 1).FirstOrDefault();
var team = context.Teams.Where(f => f.Id == 3).FirstOrDefault();
person.Teams.Add(team);
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}
using (var context = new TestContext())
{
context.People.Attach(person);
//i'm not sure if this foreach is necessary, you can try without it to see if it works
foreach (var team in person.Teams)
{
context.Teams.Attach(team);
}
context.Entry(person).State = EntityState.Modified;
context.SaveChanges();
}