System.ArgumentException: The type String[,] does not represent a sequence

.NET 6, ASP.NET, EF Core, PostgresPro

Изначально хотел перевести свой небольшой проект на ASP.NET с .NET 5 на .NET 6. Однако при попытке обращения к БД (запросе сущностей) начала возникать ошибка. Позже я попытался удалить БД и миграции и создать заново. При попытке создания первой миграции возникла та же самая ошибка.

В итоге, я создал полностью новый проект ASP.NET на .NET 6 и скопировал в него только файлы классов (вряд ли это должно было как-то повлиять, но вдруг...). При попытке создания инициирующей миграции осталась та же самая ошибка.

Полный вывод ошибки:

PM> Add-Migration InitialCreate
Build started...
Build succeeded.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.ArgumentException: The type String[,] does not represent a sequence
   at System.SharedTypeExtensions.GetSequenceType(Type type)
   at Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer`1.CreateDefaultSnapshotExpression(Boolean favorStructuralComparisons)
   at Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer`1..ctor(Boolean favorStructuralComparisons)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer.CreateDefault(Type type, Boolean favorStructuralComparisons)
   at Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping.<>c.<get_KeyComparer>b__18_0(CoreTypeMapping c)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping.get_KeyComparer()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Property.GetKeyValueComparer()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Property.Microsoft.EntityFrameworkCore.Metadata.IProperty.GetKeyValueComparer()
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.RuntimeModelConvention.Create(IProperty property, RuntimeEntityType runtimeEntityType)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.RuntimeModelConvention.Create(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.RuntimeModelConvention.ProcessModelFinalized(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.OnModelFinalized()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.<>c.<Initialize>b__5_0(IModel model)
   at Microsoft.EntityFrameworkCore.Infrastructure.AnnotatableBase.<>c__30`2.<GetOrAddRuntimeAnnotationValue>b__30_0(String n, ValueTuple`3 t)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd[TArg](TKey key, Func`3 valueFactory, TArg factoryArgument)
   at Microsoft.EntityFrameworkCore.Infrastructure.AnnotatableBase.GetOrAddRuntimeAnnotationValue[TValue,TArg](String name, Func`2 valueFactory, TArg factoryArgument)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, ModelCreationDependencies modelCreationDependencies, Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__8_4(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Exception has been thrown by the target of an invocation.

Ещё информация

В проекте используются пакеты NuGet: Microsoft.AspNetCore.Authentication.JwtBearer, Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Tools, Npgsql.EntityFrameworkCore.PostgreSQL.

Используются, соответственно, их версии 6.0.0.

Если выбрать (что в изначальном проекте, который я пытался портировать на новую версию платформы, что в новом созданном для проверки) версию платформы .NET 5.0 и выбрать версии тех же пакетов соответствующие (5.0.12 и 5.0.10 для NpgSql), то и запросы отрабатывают, и миграции создаются и с новыми БД, и со старыми.

Собственно, вопрос

С чем связана ошибка? Я нагуглить чего-то соответствующего не смог, и саму природу ошибки, честно говоря, не понимаю (ну то есть, как я понимаю, вместо последовательности символов приходит двумерный массив String, но в каком аспекте это может быть связано с непосредственно моим кодом я не понимаю).

Список "критических изменений" в EF Core 6 на MSDN я просматривал, вроде бы ничего связанного тоже не увидел.


Ответы (1 шт):

Автор решения: Nerkat

Пока описывал проблему, похоже, нашёл её источник в своём коде.

В одной из моделей у меня тип поля модели (столбца таблицы) был задан в виде двумерного массива:

public string[,] Additions { get; set; }

Поскольку в PostgresPro как таковые двумерные (прямоугольные) массивы разрешены, я, видимо, решил, что и EF Core разрешает описывать подобный тип полей в модели.

Однако я проверил созданную (с использованием .NET Core 3.1 и .NET 5 и соответствующих им версий EF Core и остальных пакетов) БД - в ней столбец Additions имеет тип text[].

То есть, как я понимаю, старые версии EF Core маппили двумерный массив в обычный массив, а новая версия явно ругается на такое описание для столбца в модели.

Ещё могу добавить, что на сайте NpgSql в документации для EF Core в разделе Arrays ничего не сказано про возможности описания средствами EF Core двумерных массивов.

Если всё так, то ошибка дурацкая, но пусть уже будет тут опубликована, мало ли - кому-то тоже поможет.


PS
Если я не прав где-то в выводах - поправьте, пожалуйста.

→ Ссылка