EF6 -> EFCore 3.1 Left outer Joins

90 Views Asked by At

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.DbSet1[Dal.Ingredient]' of method 'System.Linq.IQueryable1[Dal.Ingredient] Where[Ingredient](Microsoft.EntityFrameworkCore.DbSet1[Dal.Ingredient], System.Linq.Expressions.Expression1[System.Func2[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 :(

0

There are 0 best solutions below