I have modified my EF core entities, to swap out all List
s for ICollection
s, to adhere to my new code linter rules. So why can’t I do this anymore:
var allVgnItms1 = context.VgnItms.ToList();
without it throwing:
Exception thrown: ‘System.ArgumentException’ in
System.Linq.Expressions.dll: ‘Expression of type
‘System.Collections.Generic.ICollection1[System.Int32]' cannot be used for parameter of type 'System.Collections.Generic.IList
1[System.Int32]’ of method
‘System.Collections.Generic.IList1[System.Int32] PopulateList[Int32](System.Collections.Generic.IList
1[System.Int32],
System.Collections.Generic.IList1[System.Int32])'' 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, List1 blockExpressions) at Microsoft.EntityFrameworkCore.Query.Internal.EntityMaterializerSource.CreateMaterializeExpression(List
1
blockExpressions, ParameterExpression instanceVariable, Expression
constructorExpression, HashSet1 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,
IReadOnlyList1& 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__DisplayClass9_0
1.b__0()
at
Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object
cacheKey, Func1 compiler) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1.GetEnumerator()
at
Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator() at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source) at
Vepo.Infrastructure.VgnItmsSearchIndexService`2.ReIndexVgnItms(VpDbContext
context) in
/Users/benjaminfarquhar/dev/vepo_back_end/Vepo.Infrastructure/Search/VgnItmsSearchIndexService/VgnItmsSearchIndexService.cs:line
59
if my VgnItm has ICollection
fields. But if I change the ICollection
s to List
s, the code above works. context.VgnItms
is a DbSet<VgnItm>
. I can’t see any documentation suggesting ICollection
doesn’t behave well with EF Core entities when performing DbSet
queries.
This is my VgnItm
class. But essentially if I swap out all the ICollection
s for List
s, the code above runs fine:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Vepo.Domain
{
[Serializable]
public class VgnItm : CreatedBySomeone
{
[Required]
public string Name { get; set; }
[Required]
public string CompanyName { get; set; }
[MaxLength(3000)]
public string Description { get; set; }
[MaxLength(900)]
public string WebPage { get; set; }
public string Instagram { get; set; }
public string Facebook { get; set; }
[Required]
public int IsNotVeganCount { get; set; } = 0;
[Required]
public int IsVeganCount { get; set; } = 0;
[Required]
public int RatingsCount { get; set; } = 0;
public double? Rating { get; set; }
[JsonIgnore]
private ICollection<int> _tags = new Collection<int>();
[Required]
[JsonPropertyName("tags")]
public ICollection<int> Tags
{
get => _tags;
set => _tags = value;
}
[JsonIgnore]
private ICollection<int> _secondaryTags = new Collection<int>();
#nullable enable
[JsonPropertyName("secondaryTags")]
public ICollection<int>? SecondaryTags
{
get => _secondaryTags;
set => _secondaryTags = value;
}
public int? PricePoint { get; set; }
[MaxLength(20)]
[JsonIgnore]
private ICollection<Image> _images = new Collection<Image>();
[JsonPropertyName("images")]
public ICollection<Image> Images
{
get => _images;
set => _images = value;
}
public string Discriminator { get; set; }
public void UpdateTags(IEnumerable<int> tags)
{
_tags = new Collection<int>(tags.ToList());
}
public void UpdateSecondaryTags(IEnumerable<int> secondaryTags)
{
_secondaryTags = new Collection<int>(secondaryTags.ToList());
}
public void UpdateImages(IEnumerable<Image> images)
{
_images = new Collection<Image>(images.ToList());
}
}
}