What automatically causes EF Core to include Collection properties?

asp.net-core c# ef-core-2.0 entity-framework-core

Question

I have this class:

public class Subject
{
    public int Id { get; set; }

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

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

    public int LevelId { get; set; }
    public int? ParentId { get; set; }
    public int Order { get; set; }

    [ForeignKey("LevelId")]
    public Level Level { get; set; }

    [ForeignKey("ParentId")]
    public Subject Parent { get; set; }

    public ICollection<Subject> Children { get; set; }

    [Column(TypeName = "datetime2")]
    public DateTime? DeletedAt { get; set; }
}

And then I have these 2 repository methods:

public Subject GetById(int subjectId)
{
    var subjectFound = _context.Subjects.Where(subj => subj.Id == subjectId)
        .SingleOrDefault();
    var subject = _mapper.Map<Subject>(subjectFound);
    if (subjectFound != null)
    {
        subject.Children = GetChildren(subject.Id).ToList();
    }
    return subject;
}

public void Update(Subject existingSubject)
{
    var subjectToUpdate = _context.Subjects.Where(subj => subj.Id == existingSubject.Id)
        .SingleOrDefault();
    if (subjectToUpdate != null)
    {
        _mapper.Map(existingSubject, subjectToUpdate);
        _context.Update(subjectToUpdate);

        SaveChildren(subjectToUpdate.Id, existingSubject.LevelId, existingSubject.Children);

        _context.SaveChanges();
    }
}

If you look at the LINQ statements for these 2 methods, they are the same just different variable name in the where clause but they have the same value that is being searched for the Id.

What's happening right now is in the first method (GetById), after the LINQ query, the Children is null the reason I have a GetChildren call inside it.

But in the second method (Update), after the LINQ query, the returned object has all its Children. They are the same query and I've checked over and over again to make sure they have the same values and they do.

I don't have any special prior code before the call to these 2; they are just called normally. So I'm really confused by this behavior. What could be causing this?

1
2
12/29/2017 11:59:02 PM

Popular Answer

First, EF Core never automatically includes related entities. EF Core does not support lazy-loading, so all related entities must either be eagerly loaded (via Include) or explicitly loaded (Load).

That said, the DbContext in EF maintains an object graph, and as objects are queried, they are persisted in that graph. Once the children were loaded once, EF can re-establish that those related entities again from the graph, without having to query the DB, which is likely what you're seeing here. However, this is not something you should rely on, as it's very much hit or miss. You essentially just got lucky that methods were called in a certain order where this worked. It's always best to assume things won't be there and act accordingly. If EF doesn't need to actually issue a query to make it happen, great, but it should be empowered to if necessary.

2
12/29/2017 3:20:23 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow