我将我的应用程序从EF4.1更新为EF6,现在我遇到了延迟加载问题。我使用EF6.x DbContext Generator来生成新的DbContext。此article的所有建议也已应用。
IEntityWithChangeTracker
或IEntityWithRelationships
ProxyCreationEnabled
和LazyLoadingEnabled
都设置为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; }
}
此外,我尝试明确设置ProxyCreationEnabled
和LazyLoadingEnabled
,但没有运气。该实体未加载为动态代理,因为此调试会话屏幕截图显示:
我还缺少什么?
答案 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块中配置了上下文,并且实际迭代直到使用块的作用域已经过去之后才会发生。