EF Core and ProjectToType eager loader and is ignoring include
Following the next example: when using ProjectToType on a queryable Mapster is eager loading the data "SomeOtherEntity" and ignores the "include take(1)".
class SomeEntity
{
private ICollection<SomeOtherEntity> MyList { get; set; }
}
class SomeOtherEntity
{
private SomeEntity myEntity { get; set; }
}
class MyModel
{
private ICollection<SomeOtherEntity> MyList { get; set; }
}
class MyOtherModel
{
private MyModel myEntity { get; set; }
}
await _dbContext.SomeEntity
.AsNoTracking()
.Where(x => x.IsActive == isActive)
.Include(x =>
x.SomeOtherEntity
.OrderByDescending(p => p.Date)
.Take(1))
.ProjectToType<MyModel>()
.ToListAsync(cancellationToken);
Mapping data this way: works fine!
var data = await _dbContext.SomeEntity
.AsNoTracking()
.Where(x => x.IsActive == isActive)
.Include(x =>
x.SomeOtherEntity
.OrderByDescending(p => p.Date)
.Take(1))
.ToListAsync(cancellationToken);
return data.Adapt<List<SomeModel>>();
I have tried something similar and noticed that the OrderBy on the SomeOtherEntity is not being executed in the query either.
I also have some issue when the intention not to include some lazy loading property but eventually it loaded when use ProjectToType.
This is a problem I too just noticed today when I saw the SELECT statement being generated with joins and I didn't do the joins/includes myself and I know EF Core doesn't eager load either unless the entities are already being tracked.
I will assume fixing this for all the use cases of queryable will prove hard and I'm not sure a mapper should be even doing that. As an optional, opt-in (i.e. explicit) feature, maybe but definitely not by default.
Can confirm that using ProjectToType<> will remove the include "where" etc. This is pretty serious as the code compiles and runs without any warning that this will happen.
Is this considered expected behaviour or a bug that could be fixed?
Updated to the latest version of Mapster recently and some of my tests suddenly started failing. Even just simply mapping a table to an output with no other methods doesn't work now.
public async Task<List<TOutput>> GetAllAsync<TEntity, TOutput>() where TEntity : class
{
return await _context.Set<TEntity>().ProjectToType<TOutput>().ToListAsync();
}
Even with this oversimplified use case, no matter how many records the table has, this always returns an empty list. But, as mentioned above, doing:
public async Task<List<TOutput>> GetAllAsync<TEntity, TOutput>() where TEntity : class
{
var entities = await _context.Set<TEntity>().ToListAsync();
return entities.Adapt<List<TOutput>>();
}
Works just fine, so there's definitely an issue with the ProjectToType<>() method.