Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Core ignoring .Include(..) without .ToList(..) indirectly

As noted in "Loading Related Data" from EF Core Documentation we can use .Include(..) to Eagerly Load navigation properties from the DbSet (or generic IQueryable<T> linking back to an EF context).

This means that, given the following models:

public class TestEntityA
{
    public int Id { get; set; }
    public int TestEntityBId { get; set; }
    public TestEntityB TestEntityB { get; set; }

    public string BProperty { get { return TestEntityB.Property; } }
}

public class TestEntityB
{
    public int Id { get; set; }
    public string Property { get; set; }
}

.. then code such as the following should work:

context.TestEntityAs
    .Include(m => m.TestEntityB)
    .Any(m => m.BProperty == "Hello World");
    /*
     * Note that the below DOES work by using the nav property directly
     * in the query, but that is not always going to be an option for
     * whatever reason. If it's .Included it should be available through
     * INNER JOINing it into the base query before the .Any runs.
     * .Any(m => m.TestEntityB.Property == "Hello World");
     */

However it doesn't.

I note that there is a caveat where .Include() could be ignored should a query not return the type that is initially requested:

If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored. [snip] By default, EF Core will log a warning when include operators are ignored.

I'm not sure how, in the above call to .Any() that is relevant. Yes, the query is not returning the original type (it's returning a bool of course) but at the same time, the Warning is also not logged to advise that it is being ignored.

My questions here are:

  • Is this a usage case that is expected to work? Should I raise a bug in EF Core?
  • If it's not expected, a workaround is as below (to call .ToList()) but that would obviously load everything, to find out if we have anything on a .Any() which could easily be a query (and would be as such in EF6). What is a workaround to get this .Any() to work on the server side thus not requiring the ToList to put it in memory?

Workaround:

context.TestEntityAs
    .Include(m => m.TestEntityB)
    .ToList()
    .Any(m => m.BProperty == "Hello World");

Full reproducible sample: https://gist.github.com/rudiv/3aa3e1bb65b86ec78ec6f5620ee236ab

like image 204
Rudi Visser Avatar asked Apr 21 '17 11:04

Rudi Visser


1 Answers

by naming convention it should be worked you can try using this piece of code to manual configure relation beetwen your models

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<TestEntityA>()
        .HasOne(x => x.TestEntityB)
        .WithMany()
        .HasForeignKey(x => x.TestEntityBId);
}
like image 153
DarkFinger Avatar answered Oct 26 '22 03:10

DarkFinger