I'm in the process of evaluating upgrading to EFCore 3.1 from EF6 and I'm stuck on simple left outer joins. We have a substantial amount of code such as the following"
IQueryable<SearchItemResponseDataModel> items = from item in db.Item
from e in db.Ingredient.Where(a => item.ItemId == a.ItemId).DefaultIfEmpty()
select new SearchItemResponseDataModel
{
ItemId = item.ItemId,
Name = item.Name,
IsActive = item.IsActive,
Description = item.Description,
Color = e.Color
};
Works fine in EF6; however, in EFCore, I receive the following exception:
Expression of type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[Dal.Ingredient]' cannot be used for parameter of type 'Microsoft.EntityFrameworkCore.DbSet
1[Dal.Ingredient]' of method 'System.Linq.IQueryable1[Dal.Ingredient] Where[Ingredient](Microsoft.EntityFrameworkCore.DbSet
1[Dal.Ingredient], System.Linq.Expressions.Expression1[System.Func
2[Dal.Ingredient,System.Boolean]])'
If I rewrite it like the following, it runs without issue:
IQueryable<SearchItemResponseDataModel> items = from item in db.Item
join e in db.Ingredient on item.ItemId equals e.ItemId into ef
from e in ef.DefaultIfEmpty()
select new SearchItemResponseDataModel
{
ItemId = item.ItemId,
Name = item.Name,
IsActive = item.IsActive,
Description = item.Description,
Color = e.Color
};
So, it appears it's caused by the conflicted namespace between System.Linq and Microsoft.EntityFrameworkCore.
I added
public static class DbSetExtensions
{
public static IAsyncEnumerable<TEntity> AsAsyncEnumerable<TEntity>(this Microsoft.EntityFrameworkCore.DbSet<TEntity> obj) where TEntity : class
{
return Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsAsyncEnumerable(obj);
}
public static IQueryable<TEntity> Where<TEntity>(this Microsoft.EntityFrameworkCore.DbSet<TEntity> obj, System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate) where TEntity : class
{
return System.Linq.Queryable.Where(obj, predicate);
}
}
to the base of my class per the recomendation here: https://github.com/dotnet/efcore/issues/18220
If I remove this override, this works:
IQueryable<SearchItemResponseDataModel> items = from item in db.Item.AsQueryable()
from e in db.Ingredient.AsQueryable().Where(a => item.ItemId == a.ItemId).DefaultIfEmpty()
select new SearchItemResponseDataModel
{
ItemId = item.ItemId,
Name = item.Name,
IsActive = item.IsActive,
Description = item.Description,
Color = e.Color
};
It would be great to have an override so I don't need to add .AsQueryable() everywhere :(