Entity Framework - Stop Lazy Loading Related Entities On Demand?

leen3o picture leen3o · Apr 15, 2015 · Viewed 14.7k times · Source

I have Entity Framework set up and it works fine most of the time I need it. I have a structure like so

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; }
}

As you can see I have a number of related entities which are lists. These are mapped as standard and are lazy loaded so I can call Topic.Posts or Topic.TopicNotifications etc... (Mappings below)

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");
                });

This is all an well. But on a couple of occasions I have the need to manually populate Topic.Posts and Topic.Favorites.

But if I try and set Topic.Posts = SomeCollection it triggers the lazy load and loads all the posts first, and then lets me set my collection so I get two sets of sql executed (The first I don't want)

Is there anyway, to switch off the lazy loading manually on demand for just when I want to set the collection manually?

Hope that makes sense... :/

Answer

AllMadHare picture AllMadHare · Apr 20, 2015

You would be better to turn off lazy loading by default and instead specify when you want to load the extra data in the first place. EF is set up to allow Eager loading by using the .Include() function on your query, with lazy loading it can get messy if you start turning it on/off for various functions, you're better to just turn it off and manage what/when you want data loaded if you're feeling a need to turn it off.

See https://msdn.microsoft.com/en-nz/data/jj574232.aspx for specific examples and a breakdown of the different ways you can eager/lazy load data. The first example shows how you could pull through posts off a blog, which is similar to what you are wanting to acheive.

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