Skip to content

Can persist IEnumerable<string>, but not retrieve #34685

@Red-F

Description

@Red-F

Sample project

Please find a complete project at https://github.com/Red-F/EfCoreIssue

Description

I am using a property defined as IEnumerable. Migrations will add the column, saving will fill the column with the json representation, but reading throws:

Expression of type 'System.Collections.Generic.IEnumerable1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IList1[System.String]' of method 'System.Collections.Generic.IList1[System.String] PopulateList[String](System.Collections.Generic.IList1[System.String], System.Collections.Generic.IList`1[System.String])' (Parameter 'arg0')

Include your code

Summary, this class

public class WithIEnumerable
{
    private WithIEnumerable()
    {
        Id = 0;
        Name = string.Empty;
        Tags = [];
    }
    
    public int Id { get; }
    public string Name { get; }
    public IEnumerable<string> Tags { get; }

    public WithIEnumerable(string name, IEnumerable<string> tags)
    {
        Name = name;
        Tags = tags;
    }
}

public class WithIEnumerableConfiguration : IEntityTypeConfiguration<WithIEnumerable>
{
    public void Configure(EntityTypeBuilder<WithIEnumerable> builder)
    {
        builder.ToTable("WithIEnumerable");
        builder.HasKey(o => o.Id);
        builder.Property(o => o.Id).IsRequired().ValueGeneratedOnAdd();
        builder.Property(o => o.Name).IsRequired().HasMaxLength(100);
        builder.Property(o => o.Tags);
    }
}

Will throw an exception when retrieving the data like:

    [Fact]
    public async Task StringIEnumerable_IsStoredSuccessful()
    {
        await using var writeDbContext = DemoDbContext.Create();
        writeDbContext.Set<WithIEnumerable>().Add(new WithIEnumerable("aName", ["aTag1", "aTag2"]));
        await writeDbContext.SaveChangesAsync();

        await using var readDbContext = DemoDbContext.Create();
        var result = await readDbContext.Set<WithIEnumerable>().FirstAsync();

        using var scope = new AssertionScope();
        result.Should().NotBeNull();
        result.Tags.Should().HaveCount(2);
    }

Stack trace

System.ArgumentException
Expression of type 'System.Collections.Generic.IEnumerable`1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IList`1[System.String]' of method 'System.Collections.Generic.IList`1[System.String] PopulateList[String](System.Collections.Generic.IList`1[System.String], System.Collections.Generic.IList`1[System.String])' (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 Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 20
   at Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 24
   at Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 24
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass46_0.<<InvokeTestMethodAsync>b__1>d.MoveNext() in /_/src/xunit.execution/Sdk/Frameworks/Runners/TestInvoker.cs:line 253
--- End of stack trace from previous location ---
   at Xunit.Sdk.ExecutionTimer.AggregateAsync(Func`1 asyncAction) in /_/src/xunit.execution/Sdk/Frameworks/ExecutionTimer.cs:line 48
   at Xunit.Sdk.ExceptionAggregator.RunAsync(Func`1 code) in /_/src/xunit.core/Sdk/ExceptionAggregator.cs:line 90

Verbose output

dotnet test Demos.csproj
  Determining projects to restore...
  All projects are up-to-date for restore.
  Demos -> /home/fred/projects/EfCoreIssue/bin/Debug/net8.0/Demos.dll
Test run for /home/fred/projects/EfCoreIssue/bin/Debug/net8.0/Demos.dll (.NETCoreApp,Version=v8.0)
VSTest version 17.11.0 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.80]     Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful [FAIL]
  Failed Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful [689 ms]
  Error Message:
   System.ArgumentException : Expression of type 'System.Collections.Generic.IEnumerable`1[System.String]' cannot be used for parameter of type 'System.Collections.Generic.IList`1[System.String]' of method 'System.Collections.Generic.IList`1[System.String] PopulateList[String](System.Collections.Generic.IList`1[System.String], System.Collections.Generic.IList`1[System.String])' (Parameter 'arg0')
  Stack Trace:
     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 Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 20
   at Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 24
   at Demos.PrimitiveCollections.PrimitiveCollectionDemos.StringIEnumerable_IsStoredSuccessful() in /home/fred/projects/EfCoreIssue/PrimitiveCollections/PrimitiveCollectionDemos.cs:line 24
--- End of stack trace from previous location ---

Failed!  - Failed:     1, Passed:     1, Skipped:     0, Total:     2, Duration: 80 ms - Demos.dll (net8.0)```

### Include provider and version information

EF Core version: 8.0.8
Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer)
Target framework: .NET 8.0
Operating system: Linux
IDE: Command line

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions