我有这段代码
public int Update(Item item)
{
using (var ctx = new DataConext())
{
ctx.Entry(item).State = EntityState.Modified;
return ctx.SaveChanges();
}
}
Class Item
{
public string Name {get;set;}
public ICollection<Foobar> Foos {get;set;}
}
Class Foobar
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
让我们说:
item.Foos.ElementAt(0).FirstName = "edited name"
执行了SaveChanged(),但我在数据库中有'旧'值,而不是'编辑过的名字'......
我可以在调试中看到Local中的正确更改。
答案 0 :(得分:2)
看起来您的对象来自与您正在使用的对象不同的上下文。在这种情况下,您不能使用泛型,因为您需要在Foobar集合中执行foreEach并单独更改每个项目的状态。
这里有一个断开连接的实体图,因此实体断开连接并且更改跟踪丢失。您只需设置主实体的状态,因此EF假定其他所有内容都保持不变。
Jullie Lerman的书是了解其工作原理的好资料
我会做的是我会将此方法保留为简单实体,但将其设置为虚拟,以便您可以继承此repo以创建特定的实体repos,并使用更适合实体的更具体的实现覆盖更新方法,例如您的实体示例
答案 1 :(得分:0)
您正在上下文中加载对象并保存在另一个上下文中。删除using (var ctx = new DataConext())
块,并搜索到达加载项的上下文的方法,然后调用SaveChanges();
另一种方法是将上下文传递给方法,如public int Update(Item item, DbContext context)
并保存更改
答案 2 :(得分:0)
Class Item
{
public string Name {get;set;}
public ICollection<Foobar> Foos {get;set;}
}
您需要Include
将Foos包含在对象管理器中。现在,它是急切的装载。无论您是否装载该物品,都必须加入该物品。
您应该使用include
。
或者您可以使用virtual
让它们延迟加载。