Skip to content

EF Core 8 & 9 throw when "external" sets of primitive types are included in select #35568

Open
@ravindUwU

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 🙂.

  • EF core 7.0.20 runs the queries with no errors.

  • EF core 8.0.12 & 9.0.1 throw as described.

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

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions