EF 6 延迟加载已禁用,但仍会加载子记录

EF 6 Lazy Loading Disabled but Child Record Loads Anyway

我首先使用 EF6 代码。有两个 table,LessonLessonSectionsLessonSections table 有一个指向 Lesson.Id

的外键

这是删除了 none 重要字段的 Lesson class:

public partial class Lesson
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Lesson()
    {
        LessonSections = new HashSet<LessonSection>();
    }

    [StringLength(50)]
    public string Id { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<LessonSection> LessonSections { get; set; }
}

这是我启动数据模型的方式:

    var db = new Touch_Type_Trainer_DB.DataModel();
    db.Configuration.ProxyCreationEnabled = false;
    db.Configuration.LazyLoadingEnabled = false;

就在我第一次调用数据库检索数据库中的第一课后,生成的对象没有LessonSections

然后我进行第二次调用以将这些部分检索到一个单独的对象中。 (它们必须位于单独的对象中,因为我想将它们序列化为 JSON 字符串,并且如果我使用标准 EF LazyLoading,序列化程序会在 LessonLessonSections 之间的循环引用上停止。 )

现在我的原始对象有两个部分从数据库加载,即使我从未访问过 LessonSections 属性 并且即使 LazyLoadingEnabled 设置为 False!

为什么 LessonSections 会加载?

编辑:

我正在使用 Newtonsoft 将我的对象序列化为 JSON 字符串。也许 Newtonsoft 中有一个我应该设置的配置设置,这样它就不会陷入循环引用问题?

此外,我确实希望为大部分代码启用 LazyLoading,只是不为序列化部分启用。

这对您来说是个问题,还是您只是想知道为什么会这样?

DBContext 为您跟踪所有引用。当您加载这些部分时,它知道这些课程有对它们的引用,并为您连接它。

您可以通过断开对象或从不同的 dbcontext 加载部分来停止此操作

myDbContext.Entry(someLesson).State=Detached;

关于序列化问题,请参阅此问答How Do You "Really" Serialize Circular Referencing Objects With Newtonsoft.Json?

http://johnnycode.com/2012/04/10/serializing-circular-references-with-json-net-and-entity-framework/

在我看来,这是 EF 的不良行为。

EF 以这种方式工作(就像您可能已经注意到的那样):当您禁用延迟加载时,关系不会被解析(即使您访问 属性 也不会加载属性)。 在您的情况下,您可以访问 les.LessonSections 并且您看到它为 null 或(在您的情况下,您在 Lesson 构造函数中初始化它)为空。

如果您使用相同的上下文访问未加载延迟加载的对象或集合(构建查询并实现它),EF 会自动尝试解决延迟加载期间的关系(如果对象未加载)有代理)。这是您的行为,在一个完全不同的查询中,您访问 LessonSections 并且 EF 解决了 Lesson 中的关系。

乍一看这是一个很好的行为,但最后您可能会遇到不一致的上下文(一些对象的关系已解决,而另一些则没有),这可能会导致应用程序出现错误。恕我直言,如果 EF(禁用 LazyLoad)根本不解决关系并且如果您需要解决它,则行为可能会更加一致。但这只是我的意见。

关于您的问题,您可以像另一个答案中建议的那样分离对象,或者在同一工作单元中使用两个不同的上下文(具有相同或不同的连接)。我更喜欢(通常我使用)第二种方法,尽快禁用延迟加载来处理上下文。