Open
Description
Bug description
I also noticed that when a variable that is a HashSet<int>
(for example) is included in the select expression, EF Core 8 & 9 throw errors that seem to be JSON-serialization related. Like in #35567, this issue doesn't seem to occur when a non-primitive variable is included in the select expression.
Please refer to the reproduction and the stack trace included below 🙂.
Your code
public class Program
{
public static async Task Main()
{
var db = new Db();
var listOfInt = new List<int> { 1 };
var setOfDouble = new HashSet<double> { 1d };
var anObject = new { };
Write($"EF Core {typeof(DbContext).Assembly.GetName().Version}");
Write("\n1. SELECT e.Id, listOfInt");
await db.Entities.Select((e) => new { e.Id, listOfInt }).ToListAsync();
Write("\n2. SELECT e.Id, setOfInt");
try { await db.Entities.Select((e) => new { e.Id, setOfDouble }).ToListAsync(); }
catch (Exception e) { Console.WriteLine(e); }
Write("\n3. SELECT e.Id, listOfInt, setOfInt");
try { await db.Entities.Select((e) => new { e.Id, listOfInt, setOfDouble }).ToListAsync(); }
catch (Exception e) { Console.WriteLine(e); }
Write("\n4. SELECT e.Id, listOfInt, setOfInt, anObject");
try { await db.Entities.Select((e) => new { e.Id, listOfInt, setOfDouble, anObject }).ToListAsync(); }
catch (Exception e) { Console.WriteLine(e); }
}
public class Db : DbContext
{
public DbSet<Entity> Entities { get; init; } = null!;
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("...");
options.LogTo(Console.WriteLine, LogLevel.Information);
}
}
[Table("entity")]
[PrimaryKey(nameof(Id))]
public class Entity
{
[Column("id")]
public required int Id { get; set; }
}
public static void Write(string s)
{
var c = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(s);
Console.ForegroundColor = c;
}
}
Stack traces
With setOfDouble
as a HashSet<double>
, the stack trace is:
An exception occurred while iterating over the results of a query for context type 'TestEfCore.Program+Db'.
System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.HashSet`1[System.Double]' to type 'System.Collections.Generic.IList`1[System.Double]'.
at Microsoft.EntityFrameworkCore.Storage.Json.JsonCollectionOfStructsReaderWriter`2.FromJsonTyped(Utf8JsonReaderManager& manager, Object existingObject)
at Microsoft.EntityFrameworkCore.Storage.Json.JsonValueReaderWriter`1.FromJson(Utf8JsonReaderManager& manager, Object existingObject)
at Microsoft.EntityFrameworkCore.Storage.Json.JsonValueReaderWriter.FromJsonString(String json, Object existingObject)
at lambda_method11(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at TestEfCore.Program.Main() in ~\Projects\TestWeb\TestEfCore\Program.cs:line 27
As an IReadOnlySet<double>
instead:
An exception occurred while iterating over the results of a query for context type 'TestEfCore.Program+Db'.
System.MissingMethodException: Cannot dynamically create an instance of type 'System.Collections.Generic.IReadOnlySet`1[System.Double]'. Reason: Cannot create an instance of an interface.
at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
at System.RuntimeType.ActivatorCache.Create(RuntimeType type)
at System.RuntimeType.IGenericCacheEntry`1.CreateAndCache(RuntimeType type)
at System.RuntimeType.CreateInstanceOfT()
at System.Activator.CreateInstance[T]()
at Microsoft.EntityFrameworkCore.Storage.Json.JsonCollectionOfStructsReaderWriter`2.FromJsonTyped(Utf8JsonReaderManager& manager, Object existingObject)
at Microsoft.EntityFrameworkCore.Storage.Json.JsonValueReaderWriter`1.FromJson(Utf8JsonReaderManager& manager, Object existingObject)
at Microsoft.EntityFrameworkCore.Storage.Json.JsonValueReaderWriter.FromJsonString(String json, Object existingObject)
at lambda_method11(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at TestEfCore.Program.Main() in ~\Projects\TestWeb\TestEfCore\Program.cs:line 27
Verbose output
EF Core version
9.0.1
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.NET 9.0.102
Operating system
Windows 11
IDE
Microsoft Visual Studio Professional 2022 x64 17.12.4