急切加载工作正常时,EF6延迟加载不起作用

时间:2014-03-03 17:01:10

标签: c# entity-framework-6

我将我的应用程序从EF4.1更新为EF6,现在我遇到了延迟加载问题。我使用EF6.x DbContext Generator来生成新的DbContext。此article的所有建议也已应用。

  • 我的课程是公开的
  • 没有密封,不是抽象的
  • 拥有公共构造函数
  • 不要同时实施IEntityWithChangeTrackerIEntityWithRelationships
  • ProxyCreationEnabledLazyLoadingEnabled都设置为true
  • 导航属性是虚拟的

对我来说看起来也很奇怪的是,如果我明确地将导航属性包含在Include("...")中,那么它就会被加载。

我的POCO和DbContext的简化版本:

public partial class Ideation
{
    public Ideation()
    {

    }

    public long Id { get; set; }
    public Nullable<long> ChallengeId { get; set; }

    public virtual Challenge Challenge { get; set; }
}

public partial class Challenge
{
    public Challenge()
    {
        this.Ideations = new HashSet<Ideation>();
    }

    public long Id { get; set; }

    public virtual ICollection<Ideation> Ideations { get; set; }
}

public partial class BoxEntities : DbContext
{
    public TIBoxEntities()
        : base("name=BoxEntities")
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Ideation> Ideations { get; set; }
    public virtual DbSet<Challenge> Challenges { get; set; }
}

此外,我尝试明确设置ProxyCreationEnabledLazyLoadingEnabled,但没有运气。该实体未加载为动态代理,因为此调试会话屏幕截图显示:

Debug

我还缺少什么?

2 个答案:

答案 0 :(得分:4)

可能发生这种情况的情况是,您尝试使用Find加载的实体已作为非代理对象附加到上下文。例如:

using (var context = new MyContext())
{
    var ideation = new Ideation { Id = 1 }; // this is NOT a proxy
    context.Ideations.Attach(ideation);

    // other stuff maybe ...

    var anotherIdeation = context.Ideations.Find(1);
}

anotherIdeation将是已经附加的非代理,并且无法进行延迟加载。使用var anotherIdeation = context.Ideations.SingleOrDefault(i => i.Id == 1);运行数据库查询甚至没有帮助,因为查询的默认合并选项是AppendOnly,即只有在没有附加实体的情况下才会添加新实体键。因此,anotherIdeation仍然是非代理人。

Local方法中致电Find之前,您可以使用GetById检查实体是否已经附加:

bool isIdeationAttached = context.Ideations.Local.Any(i => i.Id == id);

答案 1 :(得分:0)

Per @ ken2k的评论,以EF 4开头的新模型的默认设置是默认启用延迟加载。使用EF 1,不允许使用。如果将模型从1迁移到4,则默认情况下将其保持关闭状态。您需要修改上下文以启用它。

话虽如此,你通过调试表明它是真的。在这种情况下,请检查您的使用方案。是否有可能在获取子对象之前处理了您的上下文。通常,当数据绑定到LINQ查询时,我们会看到这一点,其中在Using块中配置了上下文,并且实际迭代直到使用块的作用域已经过去之后才会发生。