Count with Take or Skip throws InvalidCastException
See original GitHub issueQuery throws InvalidCastException
when Take
or Skip
is used after Select
which includes ternary expression with join (in the sample the condition doesn’t really make sense since Country
doesn’t have type hierarchy registered, but effect is the same).
This seems to be contination of https://github.com/aspnet/EntityFrameworkCore/issues/16722
context.Cities
.Select(c => new
{
Name = c.Name,
Country = c.Country is Country ?
new
{
Name = c.Country.Name,
} :
null,
})
.Take(20)
.Count();
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Microsoft.EntityFrameworkCore.Query.SqlExpressions.SqlFunctionExpression' to type 'System.Linq.Expressions.ConstantExpression'.
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.RelationalProjectionBindingRemovingExpressionVisitor.VisitBinary(BinaryExpression binaryExpression)
at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor visitor, BlockExpression block)
at System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression node)
at System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Count[TSource](IQueryable`1 source)
at test_efcore_count.Program.Main(String[] args) in D:\Projects\test-efcore-count\test-efcore-count\Program.cs:line 112
at test_efcore_count.Program.<Main>(String[] args)
Steps to reproduce
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace test_efcore_count
{
class Country
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<City> Cities { get; set; }
}
class City
{
public int Id { get; set; }
public string Name { get; set; }
public Country Country { get; set; }
public int CountryId { get; set; }
}
class MapContext : DbContext
{
public MapContext(DbContextOptions<MapContext> options)
: base(options)
{ }
public DbSet<Country> Countries { get; set; }
public DbSet<City> Cities { get; set; }
}
class Program
{
static async Task Main(string[] args)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(x => x.AddConsole());
serviceCollection.AddDbContext<MapContext>(dbContextBuilder =>
{
dbContextBuilder.UseSqlServer("Server=.;Initial Catalog=test-efcore-count;Integrated Security=True");
});
using var serviceProvider = serviceCollection.BuildServiceProvider();
Console.WriteLine("Preparing database..");
using (var scope = serviceProvider.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<MapContext>())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
}
Console.WriteLine("Inserting data..");
using (var scope = serviceProvider.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<MapContext>())
{
context.Countries.Add(new Country()
{
Name = "Czech Republic",
Cities = new[]
{
new City() { Name = "Prague" },
new City() { Name = "Brno" },
}
});
context.Countries.Add(new Country()
{
Name = "Spain",
Cities = new[]
{
new City() { Name = "Madrid" },
new City() { Name = "Barcelona" },
}
});
await context.SaveChangesAsync();
}
Console.WriteLine("Printing data..");
using (var scope = serviceProvider.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<MapContext>())
{
var query = context.Cities
.Select(c => new
{
Name = c.Name,
Country = c.Country is Country ?
new
{
Name = c.Country.Name,
} :
null,
});
// works
var list = query.Take(20).ToArray();
foreach (var item in list)
{
Console.WriteLine($"{item.Name} in {item.Country.Name}");
}
// error
var total = query.Take(20).Count();
Console.WriteLine($"Database contains {total} cities");
}
}
}
}
Further technical details
EF Core version: 3.0.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.0 Operating system: Windows 10 1903 IDE: Visual Studio 2019 16.3.4
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:10 (5 by maintainers)
Top Results From Across the Web
c# - SingleResult<myObject> .ToList or .Count throws an ...
As a single element you can't convert it to a list of more than one element or count how many elements it has....
Read more >C# ienumerable.count() raises an invalidcastexception
I just found out than in the code of the Count() method it cast from IEnumerable to ICollection. (ICollection<tsource> collection = source as ......
Read more >System.InvalidCastException: Unable to cast object of type ...
HI, I received this message : System.InvalidCastException: Unable to cast object of type 'System.Int64' to type 'System.Int32'.
Read more >Casting vs “as” – embracing exceptions
If the actual value of the expression is a non-null reference to an incompatible type, casting will throw an InvalidCastException whereas the " ......
Read more >SSRS 2014 + Report Manager Error + System. ...
Hi All - I'm getting a very strange error in SSRS 2014. Both Report Manager and Reporting Service are now unavailable.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Facing the same issue in EF Core 3.1.4. Did you happen to find a workaround @TsengSR?
@ajcvickers wrote:
But @Kukkimonsuta had this question about that statement:
If the maintainers find some time to reply, I’d like to understand if this is currently a bug in EF Core, or if it’s actually working as intended. Thank you
I’ve taken another look at this, and it seems to be resolved in EF Core 5.0 - please try using the recently-released 5.0.0-rc2.