Skip to content

[EF Core 8.x] - Primitive Collections doesn't work with ICollection, while querying data. #35502

Open
@Morasiu

Description

Bug description

Primitive Collections doesn't work with ICollection, while querying data.

According to this example it should work.

Note: IList, List and T[] works.

EFCoreICollectionBug.zip

Your code

// See https://aka.ms/new-console-template for more information

using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();
var context = new ApplicationDbContext(new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseSqlite(connection)
    .Options);
context.Database.EnsureCreated();

var myDataWithList = new MyModelWithList
{
    MyEnums = new List<MyEnum> { MyEnum.Test1, MyEnum.Test2 }
};

context.MyModelWithLists.Add(myDataWithList);
await context.SaveChangesAsync();
context.ChangeTracker.Clear();

var dataWithList = await context.MyModelWithLists.FirstAsync(); // no error

// ERORR BELOW

var myData = new MyModel
{
    MyEnums = new List<MyEnum> { MyEnum.Test1, MyEnum.Test2 }
};

context.MyModels.Add(myData);
await context.SaveChangesAsync();
context.ChangeTracker.Clear();

var data = await context.MyModels.FirstAsync(); // error here


// CLASS DEFINITIONS
public enum MyEnum
{
    Test1,
    Test2,
    Test3
}

public class MyModel
{
    public Guid Id { get; set; }
    public ICollection<MyEnum> MyEnums { get; set; } = [];
}

public class MyModelWithList
{
    public Guid Id { get; set; }
    public List<MyEnum> MyEnums { get; set; } = [];
}

public sealed class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }

    public DbSet<MyModel> MyModels { get; set; } = null!;
    public DbSet<MyModelWithList> MyModelWithLists { get; set; } = null!;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MyModel>()
            .HasKey(x => x.Id);

        modelBuilder.Entity<MyModel>()
            .Property(x => x.MyEnums)
            .HasMaxLength(1024);
        
        modelBuilder.Entity<MyModelWithList>()
            .HasKey(x => x.Id);

        modelBuilder.Entity<MyModelWithList>()
            .Property(x => x.MyEnums)
            .HasMaxLength(1024);
    }
}

Stack traces

Unhandled exception. System.ArgumentException: Expression of type 'System.Collections.Generic.ICollection`1[EFCoreICollectionBug.MyEnum]' cannot be used for parameter of type 'System.Collections.Generic.IList`1[EFCoreICollectionBug.MyEnum]' of method 'System.Collections.Generic.IList`1[EFCoreICollectionBug.MyEnum] PopulateList[MyEnum](System.Collections.Generic.IList`1[EFCoreICollectionBug.MyEnum], System.Collections.Generic.IList`1[EFCoreICollectionBug.MyEnum])' (Parameter 'arg0')
   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.<AddInitializeExpressions>g__CreateMemberAssignment|14_0(Expression parameter, MemberInfo memberInfo, IPropertyBase property, Expression value)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.AddInitializeExpressions(HashSet`1 properties, ParameterBindingInfo bindingInfo, Expression instanceVariable, List`1 blockExpressions)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.CreateMaterializeExpression(List`1 blockExpressions, ParameterExpression instanceVariable, Expression constructorExpression, HashSet`1 properties, ParameterBindingInfo bindingInfo)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.CreateMaterializeExpression(EntityMaterializerSourceParameters parameters, Expression materializationContextExpression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.CreateFullMaterializeExpression(ITypeBase concreteTypeBase, ValueTuple`4 materializeExpressionContext)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.MaterializeEntity(StructuralTypeShaperExpression shaper, ParameterExpression materializationContextVariable, ParameterExpression concreteEntityTypeVariable, ParameterExpression instanceVariable, ParameterExpression entryVariable)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.ProcessEntityShaper(StructuralTypeShaperExpression shaper)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.EntityMaterializerInjectingExpressionVisitor.Inject(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.InjectEntityMaterializers(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression shaperExpression, RelationalCommandCache& relationalCommandCache, IReadOnlyList`1& readerColumns, LambdaExpression& relatedDataLoaders, Int32& collectionId)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitShapedQuery(ShapedQueryExpression shapedQueryExpression)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.VisitExtension(Expression extensionExpression)
   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__DisplayClass12_0`1.<ExecuteAsync>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in D:\Projekty\EFCoreICollectionBug\EFCoreICollectionBug\Program.cs:line 38
   at Program.<Main>(String[] args)

Verbose output


EF Core version

8.0.6

Database provider

Microsoft.EntityFrameworkCore.Sqlite

Target framework

.Net 8

Operating system

Windows 11

IDE

Rider 2024

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions