我试图找到一种方法来刷新我的EF实体,因为它们被另一个上下文修改了。除导航属性外,一切正常,但未更新。
改变之后,我尝试了两种方法:
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
objectContext.Refresh(RefreshMode.ClientWins, entity);
和
context.Entry(entity).Reload();
但两者都没有导致关系更新。这是代码优先模型(删除了一些东西):
public class ElementType : IElementType
{
[Key]
public Guid ID { get; set; } = Guid.NewGuid();
public virtual List<Element> Elements { get; set; }
}
public class ElementType : IElementType
{
[Key]
public Guid ID { get; set; } = Guid.NewGuid();
public virtual ElementType ElementType { get; set; }
}
我添加了一个新元素,而刷新并未更新ElementType中的Elements关系属性。我知道事情正在被其他上下文更新,因为当我关闭所有内容并重新启动时,everthing看起来就像我期望的那样。
上下文仍然是连接的,因为我可以从DB上下文中获取新实体。我甚至可以通过导航到新元素,检查它的关系属性(然后触发ElementType更新)来强制ElementType在调试器中更新它的元素集合:
如果我导航到调试器中的上下文,请检查元素集,新元素是否存在,以及关系属性是否设置正确(并引用相同的Proxy ElementType对象)。所以这是DBContext的Elements集合:
现在回到原始元素:
一切都是最新的!
所以除了刷新/更新方法之外,我确信一切正常。 This question here表明Reload应该适用于延迟加载的关系,我似乎无法找到有关如何实际刷新此集合的更多信息。任何人都知道为什么它没有像我期待的那样工作?
答案 0 :(得分:0)
感谢Cristian Szpisjak指出了DbEntityEntry的Collection方法。
我写了一个用于刷新我的集合的通用方法:
public void Refresh(object entity)
{
DbEntityEntry entry = context.Entry(entity);
entry.Reload();
var values = entity.GetType().BaseType
.GetProperties()
.Where(propertyInfo => propertyInfo.GetCustomAttributes(typeof(ReloadCollectionOnRefresh), false).Count() > 0)
.Select(propertyInfo => propertyInfo.Name);
foreach (string value in values)
{
var collection = entry.Collection(value);
collection?.Load();
}
}
使用ReloadCollectionOnRefresh自定义属性标记集合属性:
[ReloadCollectionOnRefresh]
public virtual List<MyEntity> MyEntities{ get; set; }
这只是一个非常空的属性来'标记'集合:
[AttributeUsage(AttributeTargets.Property)]
class ReloadCollectionOnRefresh : Attribute
{
// can we add checking that this is applied to a virtual collection?
}