Jef*_*fim 5 entity-framework poco navigation-properties
我在刷新相关的实体集合时遇到了一些麻烦.
基本上问题如下:
public class Student
{
public virtual ICollection<Lecture> Lectures { get; set; }
public void AddLecture(Lecture lecture)
{
Lectures.Add(lecture);
}
public void CancelChanges()
{
_context.Refresh(RefreshMode.StoreWins, this);
_context.LoadProperty(this, (o) => o.Lectures,
MergeOption.OverwriteChanges);
}
}
public class Grade
{
public virtual Student { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我有一些用于添加讲座的GUI,如果我们想要,我们可以取消编辑过程:
public void ExampleEdit()
{
Student student = _context.Students.SingleOrDefault(/* blah */);
student.AddLecture(_context.Lectures.SingleOrDefault(/* e.g. math */));
student.CancelChanges();
// At this point student SHOULD have no lectures anymore since the
// property was loaded with overwrite changes option.
// Yet the Lectures still contains the lecture we added there
}
Run Code Online (Sandbox Code Playgroud)
那么,代码是不是很糟糕?有没有我错误使用的方法?是否有可能完全重新加载整个对象?
我想你误解了MergeOption.OverwriteChanges.默认情况下,只要ObjectContext执行查询,如果缓存中已存在任何返回的对象,则忽略这些对象的新返回副本.
请注意,这一切都基于EntityKeys.基本上,检查从查询返回的对象的EntityKeys,如果缓存中已存在具有相同 EntityKey 的对象(在您的情况下,在同一个EntitySet中,Lectures),则保持现有对象不变.
但是,如果启用OverwriteChanges,则它将替换具有来自数据库的值的现有实体的当前值,即使已编辑了内存中实体.
正如您所看到的那样,您正在向学生添加一个对学生来说完全不熟悉的讲座,并且它不会被覆盖,因为它的EntityKey与根据您的LoadProperty()调用来自数据库的EntityKey不同.
一种解决方案是在LoadProperty()之前简单地清除学生对象中的所有讲座:
public void CancelChanges() {
_context.Refresh(RefreshMode.StoreWins, this);
this.Lectures.Clear();
_context.LoadProperty(this, (o) => o.Lectures, MergeOption.OverwriteChanges);
}
Run Code Online (Sandbox Code Playgroud)