刷新实体框架中的延迟加载关系

时间:2017-03-30 09:06:23

标签: c# entity-framework

我试图找到一种方法来刷新我的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在调试器中更新它的元素集合:

所以在上面的更新方法之后它是0: enter image description here

如果我导航到调试器中的上下文,请检查元素集,新元素是否存在,以及关系属性是否设置正确(并引用相同的Proxy ElementType对象)。所以这是DBContext的Elements集合:

enter image description here

现在回到原始元素:

enter image description here

一切都是最新的!

所以除了刷新/更新方法之外,我确信一切正常。 This question here表明Reload应该适用于延迟加载的关系,我似乎无法找到有关如何实际刷新此集合的更多信息。任何人都知道为什么它没有像我期待的那样工作?

1 个答案:

答案 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?
}