抱歉我的英语不好 - 我在WPF(.net 4.5)应用程序中使用EF 5(Code First)。每个窗口都有自己的上下文。
我有一个这样的模型(为简洁起见省略了代码):
public class Car
{
public string Model { get; set; }
public int BrandId { get; set; }
public virtual Brand Brand { get; set; }
}
我使用组合框允许用户将Brand
与Car
相关联。问题是,每次保存Car
时,都会保存新的重复Brand
。发生这种情况是因为我使用AsNoTracking()
加载了组合框。
现在,我使用AsNoTracking()
加载组合框,因为我无法加载在其他DbContext实例中创建的Brand
表上的更改(使用myContext.Set<Brand>().Load()
)。
所以我的问题是,如何解决这个问题?如果有另一种强制重新加载集合的方法(不使用AsNoTracking
),那就太好了。更好的是能够通知EF AsNoTracking
加载的实体不是新的。
编辑1: @标记: 谢谢,将实体附加到上下文就可以了。但是我使用了一个通用的基类来进行验证并保存所有表单的数据,所以手动附加实体并不是很实用...根据你的建议我最后这样做,在添加Car实体之后和保存之前:
var entities = (((IObjectContextAdapter)ctx).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added));
foreach (var item in entities)
{
if ((item.Entity as EntityBase).Id > 0)
{
item.ObjectStateManager.ChangeObjectState(item.Entity, EntityState.Unchanged);
}
}
(我所有的entites继承自EntityBase,我的所有密钥都是数据库生成的)。这工作正常,但我想要第二个意见......这是好还是有更简单的方法呢?
答案 0 :(得分:3)
正在发生的事情是您的上下文不知道附加到汽车的品牌,因此它创建了一个与您的外键匹配的新品牌。您应该在保存之前将品牌附加到上下文:
context.Brands.Attach(brand);
您可以在保存之前通过单独重新加载来重新加载单个品牌:
db.Entry(brand).Reload();
如果您在保存汽车时不想实际坚持对品牌进行任何更改,您可以告诉上下文品牌尚未更改,并阻止更新。
context.Entry(brand).State = EntityState.Unchanged;