In this article, we will learn when the “call is ambiguous” error happens, why the error happens, and how to work around the issue. There are still so many legacy projects using older versions of EF Core, and in those projects, this error can cause a lot of headaches for developers if they are not aware of how to resolve it.

To download the source code for this article, you can visit our GitHub repository.

So, let’s start and see what we can do about it.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

When Does the Issue Happen?

One example is when we use Entity Framework Core version 5 and System.Linq.Async Nuget packages. Entity Framework Core version 6 or later package already resolves the issue, and we will explain that later in this article.

The sample application is a .NET 7 console application and it has both Entity Framework Core (EF Core) version 5 and System.Linq.Async version 6 libraries.

So, let’s start with querying the DbSet from the DbContext:

blogDbContext.Articles.Where(x => x.Title == "Some Title");

Right after we write the code, we see the “call is ambiguous” error message on the Where method.

Why Does the Issue Happen?

The issue happens when an instance of the class has more than one method with the same name. But how can an instance have more than one method with the same name? The answer is – The C# extension method feature.

By using the feature, we can add custom methods to existing interfaces and classes. If you are unfamiliar with the feature, please refer to the Static Members, Constants and Extension Methods  in C# article.

Multiple Where Methods in the Interface

Now, let’s inspect the interfaces that contain the Where method.

The System.Linq adds Where method to the IQueryable<TSource> interface. Similarly, the System.Linq.Async library adds Where method to the IAsyncEnumerable<TSource> interface.

The DbSet<TEntity> class inherits from both IQueryable<TEntity> and IAsyncEnumerable<TEntity> interfaces. As a result, the DbSet<TEntity> class ends up having two Where methods.

This also applies to other methods such as FirstAsync, FirstOrDefaultAsync, etc. Of course,  the cause and the solutions are the same as for the Where method, so we will focus on the Where method’s case in this article.

How to Work Around the Issue?

There are several ways to work around the issue.

Use Explicit Casting

The first workaround is to use the explicit cast.

Let’s change the code:

((IQueryable<Article>)blogDbContext.Articles).Where(x => x.Title == "Some Title");

Because we explicitly cast the blogDbContext.Articles to IQueryable<Article>, the compiler knows which Where method to use.

Let’s try to cast to another interface as well:

((IAsyncEnumerable<Article>)blogDbContext.Articles).Where(x => x.Title == "Some Title");

Again, we don’t encounter the error.

Use AsQueryable And AsAsyncEnumerable Methods

The Entity Framework Core library provides AsQueryable and AsAsyncEnumerable  methods to work around the issue so that we don’t need to use the explicit cast:

blogDbContext.Articles.AsQueryable().Where(x => x.Title == "Some Title");
blogDbContext.Articles.AsAsyncEnumerable().Where(x => x.Title == "Some Title");

Both methods work as expected and we don’t encounter the issue. Basically, what this does is the same with explicit casting, but the code is more clear with fewer parenthesis!

Upgrade to Entity Framework Core Version 6 or Later

After Entity Framework Core 6, the IAsyncEnumerable<TEntity> interface inheritance was removed from the DbSet class. Therefore, if we upgrade the version of EF Core, we won’t encounter this ambiguity issue anymore.

Conclusion

In this article, we’ve learned when and why the “call is ambiguous” issue happens. Whenever you encounter the same issue in the future, we hope this article helps you to solve the issue.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!