实体:
public class Page
{
//...
public virtual Page Parent { get; set; }
}
需要将父字段设置为空。我试过了,但没有成功:
// Existing entity
Page pageAttached = db.Pages.First(x => x.Id == page.Id);
db.Entry(pageAttached).CurrentValues.SetValues(page);
if (model.ParentId != null)
pageAttached.Parent = db.Pages.First(x => x.Id == model.ParentId);
else
pageAttached.Parent = null; //does nothing
db.SaveChanges();
发布于 2012-03-16 19:26:10
Parent
不是一个“复杂字段”,它是一个“导航属性”。
如果你这样做了,它会起作用吗?
// Existing entity
Page pageAttached = db.Pages.Include(x => x.Parent).First(x => x.Id == page.Id);
db.Entry(pageAttached).CurrentValues.SetValues(page);
if (model.ParentId != null)
pageAttached.Parent = db.Pages.First(x => x.Id == model.ParentId);
else
pageAttached.Parent = null; //does nothing
db.SaveChanges();
对注释1的响应
不,我是说.Include(x => x.Parent)
。我更喜欢使用lambda重载的强类型。将魔术字符串排除在代码之外。
这样做的原因是因为DbContext使用动态生成的代理类来进行延迟加载。当您只查询.First(x => x.Id == page.Id)
时,返回的对象实际上是一个将Page
实体实现为其基类的类。(这就是集合和导航属性必须标记为virtual
的原因,以便可以在动态代理中覆盖它们。)此外,即使在db中存在父引用,动态生成的代理也具有空的父引用。
直到调用parent属性get方法,EF才会命中db来延迟加载父对象。这是当它发现数据库实际上是否具有null或非null的Parent属性时。因此,当您在父级实际延迟加载之前设置.Parent = null
时,EF不会执行任何操作,因为它已经是空的。
我建议的代码使用.Include
来加载属性。这意味着db在单个db调用中获得子代和其父元素。现在,当您设置为null时,DbContext将在您的下一次SaveChanges期间跟踪更改并删除该关系。
https://stackoverflow.com/questions/9737483
复制相似问题