EF 6 延迟加载已禁用,但仍会加载子记录
EF 6 Lazy Loading Disabled but Child Record Loads Anyway
我首先使用 EF6 代码。有两个 table,Lesson
和 LessonSections
。 LessonSections
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,序列化程序会在 Lesson
和 LessonSections
之间的循环引用上停止。 )
现在我的原始对象有两个部分从数据库加载,即使我从未访问过 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)根本不解决关系并且如果您需要解决它,则行为可能会更加一致。但这只是我的意见。
关于您的问题,您可以像另一个答案中建议的那样分离对象,或者在同一工作单元中使用两个不同的上下文(具有相同或不同的连接)。我更喜欢(通常我使用)第二种方法,尽快禁用延迟加载来处理上下文。
我首先使用 EF6 代码。有两个 table,Lesson
和 LessonSections
。 LessonSections
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,序列化程序会在 Lesson
和 LessonSections
之间的循环引用上停止。 )
现在我的原始对象有两个部分从数据库加载,即使我从未访问过 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)根本不解决关系并且如果您需要解决它,则行为可能会更加一致。但这只是我的意见。
关于您的问题,您可以像另一个答案中建议的那样分离对象,或者在同一工作单元中使用两个不同的上下文(具有相同或不同的连接)。我更喜欢(通常我使用)第二种方法,尽快禁用延迟加载来处理上下文。