我有实体框架设置,它在我需要的大部分时间都可以正常工作。我有一个像这样的结构
public partial class Topic : Entity
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime CreateDate { get; set; }
public virtual Post LastPost { get; set; }
public virtual Category Category { get; set; }
public virtual IList<Post> Posts { get; set; }
public virtual IList<TopicTag> Tags { get; set; }
public virtual MembershipUser User { get; set; }
public virtual IList<TopicNotification> TopicNotifications { get; set; }
public virtual IList<Favourite> Favourites { get; set; }
public virtual Poll Poll { get; set; }
}
正如您所看到的,我有许多列表相关的实体。这些被映射为标准并且是延迟加载的所以我可以调用Topic.Posts或Topic.TopicNotifications等...(下面的映射)
HasOptional(t => t.LastPost).WithOptionalDependent().Map(m => m.MapKey("Post_Id"));
HasOptional(t => t.Poll).WithOptionalDependent().Map(m => m.MapKey("Poll_Id"));
HasRequired(t => t.Category).WithMany(t => t.Topics).Map(m => m.MapKey("Category_Id"));
HasRequired(t => t.User).WithMany(t => t.Topics).Map(m => m.MapKey("MembershipUser_Id"));
HasMany(x => x.Posts).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete();
HasMany(x => x.TopicNotifications).WithRequired(x => x.Topic).Map(x => x.MapKey("Topic_Id")).WillCascadeOnDelete();
HasMany(t => t.Tags)
.WithMany(t => t.Topics)
.Map(m =>
{
m.ToTable("Topic_Tag");
m.MapLeftKey("TopicTag_Id");
m.MapRightKey("Topic_Id");
});
这一切都很顺利。但有几次我需要手动填充Topic.Posts和Topic.Favorites。
但是如果我尝试设置Topic.Posts = SomeCollection
它会触发延迟加载并首先加载所有帖子,然后让我设置我的集合,这样我就可以执行两组sql(第一个我不想要)
有没有,当我想手动设置集合时,按需手动关闭延迟加载?
希望有意义......:/
答案 0 :(得分:24)
最好在默认情况下关闭延迟加载,而是指定何时首先加载额外数据。 EF设置为允许通过在查询中使用.Include()函数进行Eager加载,延迟加载如果你为各种函数开启/关闭它会变得很乱,你最好关掉它如果您感觉需要关闭数据,请管理您希望加载数据的内容/时间。
有关具体示例的详细信息,请参阅https://msdn.microsoft.com/en-nz/data/jj574232.aspx,以及您可以急切/延迟加载数据的不同方法的细分。第一个示例显示了如何从博客中提取帖子,这类似于您想要实现的内容。
var topics = context.Topics
.Include(t => t.Posts)
.ToList();
答案 1 :(得分:16)
我不知道针对这个确切场景的方法,所以我必须暂时禁用/启用延迟加载。
using(var context = new MyContext())
{
context.Configuration.LazyLoadingEnabled = false;
// do your thing using .Include() or .Load()
context.Configuration.LazyLoadingEnabled = true;
}
但请注意,这是一个全局配置,因此如果在您的方案中发生这种情况,可能会出现并发问题。
答案 2 :(得分:9)
我不建议在每个请求的基础上关闭lazing加载。正如AllMadHare建议的那样,您可以完全关闭延迟加载,但这可能会强制更改加载所有数据的方式。我建议从帖子中删除虚拟关键字,以便您的课程如下所示:
public partial class Topic : Entity
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime CreateDate { get; set; }
public virtual Post LastPost { get; set; }
public virtual Category Category { get; set; }
public IList<Post> Posts { get; set; }
public virtual IList<TopicTag> Tags { get; set; }
public virtual MembershipUser User { get; set; }
public virtual IList<TopicNotification> TopicNotifications { get; set; }
public virtual IList<Favourite> Favourites { get; set; }
public virtual Poll Poll { get; set; }
}
根据此处的文档:https://msdn.microsoft.com/en-us/data/jj574232.aspx#lazyOffProperty如果需要,这将允许您延迟加载所有其他导航属性和急切加载帖子。
答案 3 :(得分:3)
由于您正在使用延迟加载,因此必须为类和集合属性生成代理。
用您自己的集合替换这些代理集合属性对我来说似乎很奇怪。你失去了变化跟踪,很可能会获得一些其他奇怪的副作用。
我建议使用代理/延迟加载并放弃更换集合的想法,或者退出使用代理并获得对生成的POCO类的完全控制。
哪种方法最适合您的需求取决于您对实体框架的总体使用情况。