Reactive: EFCore 3 conflicting extension methods

Created on 14 Oct 2019  路  8Comments  路  Source: dotnet/reactive

Given this code

using System.Linq;
using Microsoft.EntityFrameworkCore;

var agencies = await dbContext.Agencies.ToListAsync();

Where dbContext.Agencies is a DbSet<T>

If i add the System.Linq.Async nuget to the project it now breaks the build

CS0121  The call is ambiguous between the following methods or properties:
'System.Linq.Queryable.Where<TSource>(System.Linq.IQueryable<TSource>, System.Linq.Expressions.Expression<System.Func<TSource, bool>>)'
and
'System.Linq.AsyncEnumerable.Where<TSource>(System.Collections.Generic.IAsyncEnumerable<TSource>, System.Func<TSource, bool>)

Now this can be worked around by doing a static invoke:

var agencies = await EntityFrameworkQueryableExtensions.ToListAsync(dbContext.Agencies);

But as you can see this makes it very verbose. And the above is for a simple example.

A more complex one translates as follows

   var x = await ReportAccessView
            .Where(p => p.ReportId == reportId && p.UserId == userId )
            .Select(p => p.AccessRights)
            .ToListAsync();
var x = await EntityFrameworkQueryableExtensions
   .ToListAsync(
       Queryable
           .Select(
               Queryable
                   .Where(ReportAccessView, p => p.ReportId == reportId && p.UserId == userId), p => p.AccessRights));

Just wondering if there are any thoughts on handling this in a more graceful way?

Most helpful comment

Wouldn't it help if this library used a namespace other than System.Linq?

All 8 comments

/cc @bartdesmet ?

I am assuming the only fix would be for EF to not use extension methods for linq methods on types they own?

This is one of the unfortunate drawbacks of extension methods on interfaces. The moment someone implements multiple interfaces which both have extension methods defined, ambiguities can arise.

In this case, the use of AsQueryable may provide a solution, by "casting away" the IAsyncEnumerable<T> nature of DbSet<T> and only retaining IQueryable<T>:

   var x = await ReportAccessView.AsQueryable()
            .Where(p => p.ReportId == reportId && p.UserId == userId )
            .Select(p => p.AccessRights)
            .ToListAsync();

It also make it clearer what's happening remotely, versus locally.

@bartdesmet thanks. worked perfectly

ok i think this should be re-opened.

I was ok with the .AsQueryable() workaround in a top level app. since this is decision we can make as a team owning the app. But i am now in the position where i want to include System.Linq.Async as a nuget dependency in a library. I dont think i should be dictating to all users of my lib that they also need to use the .AsQueryable() workaround

thoughts?

This is still a design issue with EF core in the way they鈥檝e chosen to implement the interfaces. I don鈥檛 think there鈥檚 anything we can do here.

sigh. u r correct :(

Wouldn't it help if this library used a namespace other than System.Linq?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Thaina picture Thaina  路  5Comments

MartinEgli picture MartinEgli  路  5Comments

Sathyaish picture Sathyaish  路  3Comments

clairernovotny picture clairernovotny  路  5Comments

JanEggers picture JanEggers  路  4Comments