2015-04-15 185 views
23

我有实体框架设置,它大多数时候我需要它工作正常。我有这样的结构实体框架 - 停止延迟加载相关实体按需?

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(第一次我不希望)

无论如何,只要手动设置集合,就可以根据需要手动关闭延迟加载?

希望是有道理的...:/

+5

我感觉XY问题在这里http://meta.stackexchange.com/a/66378/134199 - 我认为你的真正问题是这个“需要手动填充Topic.Posts和Topic.Favorites”。你可能正在尝试做一些以不同方式更好地完成的事情,因为你所做的事没有任何意义。你想要做什么?为什么? –

+1

我会第二个@ErikFunkenbusch在说什么。为什么需要手动重新创建帖子和收藏夹集合? –

+0

如果你回答你正在做的事情,那么我们可能真的可以帮助你解决你真正的问题。不是你认为你有的问题,因为你认为你必须做一件特别的事情来解决你的问题问题。 –

回答

3

由于您使用延迟加载,你必须为你的类和集合属性生成的代理。

用你自己的集合替换这些代理集合属性对我来说似乎很奇怪的设计。你松开变化跟踪,最有可能获得一些其他奇怪的副作用。

我会推荐使用代理/延迟加载并放弃替换集合的想法,或退出使用代理并获得完全控制生成的POCO类。

哪种方法最适合您的需求取决于您对实体框架的整体使用情况。

12

我不知道针对这种确切情况的方法,所以我不得不暂时禁用/启用延迟加载。

using(var context = new MyContext()) 
{ 
    context.Configuration.LazyLoadingEnabled = false; 
    // do your thing using .Include() or .Load() 
    context.Configuration.LazyLoadingEnabled = true; 
} 

但请注意,这是全局配置,因此如果在您的方案中发生这种情况,可能会出现并发问题。

+1

我会反对这种方法,因为您不能再保证实体对象中包含对象的存在,所以您需要确保在尝试访问包含的对象之前总是测试空记录。在运行时切换延迟加载和代理可能会产生很多意想不到的后果,并使调试变得头痛。 – AllMadHare

+2

@AllMadHare:我同意。你的解决方案要好得多。 –

+1

@JeroenVannevel它不是一个全局属性..至少不是在EF 6中。我想有一种方法可以在全局范围内进行设置,并且该配置可能是从默认/全局设置克隆的,但Configuration(和该标志)是实例属性。 –

21

您最好在默认情况下关闭延迟加载,而是首先指定何时加载额外数据。 EF设置为允许通过在查询中使用.Include()函数进行Eager加载,如果您开始为各种功能开启/关闭开关,则可能会因为延迟加载而变得杂乱,您最好关掉它并管理它如果您需要关闭数据,您希望什么/何时加载数据。

查看https://msdn.microsoft.com/en-nz/data/jj574232.aspx了解具体示例以及您可以使用不同的方式细分/急切加载数据。第一个例子展示了如何通过博客发布帖子,这与您希望获得的成果类似。

var topics = context.Topics 
         .Include(t => t.Posts) 
         .ToList(); 
8

我不会建议关闭在每个请求基础上的延迟加载。正如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这将让你懒加载所有其他的导航性能和渴望加载信息,如果您需要。

相关问题