Отображение записи C# 9 как объекта значения с помощью EntityFrameworkCore 5

Я пытаюсь использовать record типы как объекты значений в классе C#, но когда я пытаюсь сопоставить эти типы с помощью efcore 5, он выдает исключение.

Мои занятия:

public record ZipCode
    {
        private static readonly char ZIPCODE_SEPARATOR = '-';
        private static readonly string INVALID_ZIPCODE_MESSAGE = "invalid zip code";
        private static readonly string ZIPCODE_WITH_NOT_ONLY_NUMBERS = "Invalid zip code value, must have only digits";

        private char[] _value;
        public string Value => new string(_value);

        public ZipCode(string zipCode)
        {
            _value = new char[8];
            setZipCodeValue(zipCode);
        }

        public ZipCode(ZipCode zipCode)
        {
            this._value = zipCode.Value.ToCharArray();
        }
        
        private void setZipCodeValue(string valueAsString)
        {
            if (valueAsString.Length < 8 || valueAsString.Length > 9)
            {
                throw new InvalidOperationException(INVALID_ZIPCODE_MESSAGE);
            }

            var zipCodeAsCharArray = valueAsString.ToCharArray();
            int valueArrayIndex = (int) decimal.Zero;

            foreach (var ch in zipCodeAsCharArray)
            {
                if (char.IsDigit(ch) )
                {
                    _value[valueArrayIndex] = ch;
                    valueArrayIndex++;
                }
                else if (ch.Equals(ZIPCODE_SEPARATOR))
                {
                    continue;
                }
                else
                {
                    throw new InvalidOperationException(ZIPCODE_WITH_NOT_ONLY_NUMBERS);
                }
            }
        }
    }

Главный объект:

public class DeliveryServicePriceTime
    {
        public Guid Id { get; private set; }

        public ZipCode SourceZipCode { get; private set; }
        public ZipCode DestinationZipCode { get; private set; }

        public DateTime RequestDateTime { get; private set; }

        private IList<ServicePriceTime> _servicesPriceTime;
        public IReadOnlyList<ServicePriceTime> ServicesPriceTimes => _servicesPriceTime.ToList();
        
        private DeliveryServicePriceTime()
        {
            Id = Guid.NewGuid();
        }

        public DeliveryServicePriceTime(ZipCode sourceZipCode, ZipCode destinationZipCode, IList<ServicePriceTime> servicesPriceTime) : this()
        {
            SourceZipCode = sourceZipCode;
            DestinationZipCode = destinationZipCode;
            _servicesPriceTime = servicesPriceTime;
        }

        public DeliveryServicePriceTime(string sourceZipCode, string destinationZipCode, IList<ServicePriceTime> servicesPriceTime) : this()
        {
            RequestDateTime = DateTime.UtcNow;
            this.SourceZipCode = new ZipCode(sourceZipCode);
            this.DestinationZipCode = new ZipCode(destinationZipCode);
            _servicesPriceTime = servicesPriceTime;                
        }
    }

у меня есть другой record который следующий код:

public record ServicePriceTime(DeliveryService DeliveryService, decimal Price, int Time);

Я использую свободный API для сопоставления свойств со структурой таблицы с помощью следующего кода:

public class DeliveryServicePriceTimeMappingConfiguration : IEntityTypeConfiguration<DeliveryServicePriceTime>
    {
        public void Configure(EntityTypeBuilder<DeliveryServicePriceTime> builder)
        {
            builder.ToTable("DeliveryCalcEvent");

            builder.HasKey(e => e.Id);
            builder.Property(e => e.RequestDateTime).IsRequired();

            builder.OwnsOne(e => e.SourceZipCode)
                   .Property(e => e.Value)
                   .UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction)
                   .IsRequired();

            builder.OwnsOne(e => e.DestinationZipCode)
                   .Property(e => e.Value)
                   .UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction)
                   .IsRequired();

            builder.OwnsMany(e => e.ServicesPriceTimes, ac =>
            {
                ac.OwnsOne(m => m.DeliveryService, pc =>
                {
                    pc.Property(p => p.ServiceCode).IsRequired();
                    pc.Property(p => p.ServiceName).IsRequired();
                }).UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
                ac.Property(m => m.Price).IsRequired();
                ac.Property(m => m.Time).IsRequired();
            }).UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);                
        }
    }

Я использую этот метод для обеспечения создания базы данных в классе запуска, но когда я пытаюсь запустить приложение, структура сущности не может понять мой объект записи.

это моя трассировка стека:

Microsoft.AspNetCore.Hosting.Diagnostics[6]
      Application startup exception
      System.InvalidOperationException: No suitable constructor was found for entity type 'DeliveryServicePriceTime.DestinationZipCode#ZipCode'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'zipCode' in 'DeliveryServicePriceTime.DestinationZipCode#ZipCode(string zipCode)'; cannot bind 'zipCode' in 'DeliveryServicePriceTime.DestinationZipCode#ZipCode(ZipCode zipCode)'.
         at Microsoft.EntityFrameworkCore.Metadata.Conventions.ConstructorBindingConvention.ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext`1 context)
         at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalizing(IConventionModelBuilder modelBuilder)
         at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalizing(IConventionModelBuilder modelBuilder)
         at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
         at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
         at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
         at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
         at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
         at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
         at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, 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 singletonCallSite, 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 singletonCallSite, 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__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
         at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.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_InternalServiceProvider()
         at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
         at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
         at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetRelationalService[TService](IInfrastructure`1 databaseFacade)
         at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
         at API.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider) in /API/Startup.cs:line 52
         at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
         at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
         at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
         at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
         at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass15_0.<UseStartup>b__1(IApplicationBuilder app)
         at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
         at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
         at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
Unhandled exception. System.InvalidOperationException: No suitable constructor was found for entity type 'DeliveryServicePriceTime.DestinationZipCode#ZipCode'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'zipCode' in 'DeliveryServicePriceTime.DestinationZipCode#ZipCode(string zipCode)'; cannot bind 'zipCode' in 'DeliveryServicePriceTime.DestinationZipCode#ZipCode(ZipCode zipCode)'.
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.ConstructorBindingConvention.ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext`1 context)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalizing(IConventionModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalizing(IConventionModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
   at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, 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 singletonCallSite, 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 singletonCallSite, 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__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.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_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetRelationalService[TService](IInfrastructure`1 databaseFacade)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
   at API.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider) in /API/Startup.cs:line 52
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass15_0.<UseStartup>b__1(IApplicationBuilder app)
   at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) 

Someone had any idea how to fix this?

1 ответ

Однако, если EF Core находит параметризованный конструктор с именами параметров и типами, которые соответствуют сопоставленным свойствам, он вместо этого вызовет параметризованный конструктор со значениями для этих свойств и не будет явно устанавливать типы каждого свойства с конструкторами Ef core

Мне кажется, что ваше сопоставленное имя свойства - это значение, а имя вашего параметра конструктора - почтовый индекс.

Другие вопросы по тегам