I run into following exception when mapping any value object in any aggregate:
---> System.InvalidCastException: Unable to cast object of type 'Microsoft.EntityFrameworkCore.Metadata.Internal.ComplexType' to type 'Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType'.
at Microsoft.EntityFrameworkCore.Metadata.Internal.ComplexType.<>c.<get_ConstructorBinding>b__42_0(ComplexType complexType)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Action`1 valueFactory)
at Microsoft.EntityFrameworkCore.Metadata.Internal.ComplexType.get_ConstructorBinding()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.<ValidateFieldMapping>g__Validate|24_0(ITypeBase typeBase)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.<ValidateFieldMapping>g__Validate|24_0(ITypeBase typeBase)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateFieldMapping(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.NpgsqlModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelRuntimeInitializer.Initialize(IModel model, Boolean designTime, IDiagnosticsLogger`1 validationLogger)
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(ServiceIdentifier serviceIdentifier, 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.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.Set[TEntity]()
at Venture.Server.Common.Persistence.EntityEvents.PublishedEntityEventReadRepository.GetConsumedAsync(CancellationToken cancellationToken) in C:\Users\N.Wolf\source\repos\venture-erp\src\Venture.Server.Common\Persistence\EntityEvents\PublishedEntityEventReadRepository.cs:line 25
at Venture.Server.Common.Persistence.EntityEvents.Jobs.EntityEventCleanupJob.Execute(IJobExecutionContext context) in C:\Users\N.Wolf\source\repos\venture-erp\src\Venture.Server.Common\Persistence\EntityEvents\Jobs\EntityEventCleanupJob.cs:line 18
at Quartz.Core.JobRunShell.Run(CancellationToken cancellationToken)
The 'department' aggregate and its configuration:
public class Department
{
public Guid AggregateId { get; protected set; }
public DateTime Created { get; protected set; }
public DateTime LastChanged { get; protected set; }
public Guid EditEmployeeId { get; protected set; }
public required string Name { get; init; }
public string? Comment { get; init; }
public required Address Address { get; init; }
public Guid DivisionId { get; init; }
public required Division Division { get; init; }
public List<Role> EmployeeRoles { get; init; } = [];
public List<EmployeeDepartmentAssignment> EmployeeAssignments { get; init; } = [];
public List<DepartmentPosition> Positions { get; init; } = [];
protected override void ApplyEvent(DepartmentEvent @event)
{
throw new NotImplementedException();
}
}
public record Address
{
public required string Street { get; init; }
public required string HouseNumber { get; init; }
public required string City { get; init; }
public required string PostalCode { get; init; }
public required string State { get; init; }
public required string Country { get; init; }
}
builder.ToTable("access_management_departments");
builder.HasKey(a => a.AggregateId);
builder.Property(a => a.AggregateId).HasColumnName("id").IsRequired();
builder.Property(a => a.Created).HasColumnName("created").IsRequired();
builder.Property(a => a.LastChanged).HasColumnName("last_changed").IsRequired();
builder.Property(a => a.EditEmployeeId).HasColumnName("edit_employee_id").IsRequired();
builder.Property(d => d.Name).HasColumnName("name").HasMaxLength(70).IsRequired();
builder.Property(d => d.Comment).HasColumnName("comment").HasMaxLength(200);
builder.ComplexProperty(d => d.Address, p =>
{
p.Property(a => a.Street).HasColumnName("address_street").IsRequired();
p.Property(a => a.HouseNumber).HasColumnName("address_house_number").IsRequired();
p.Property(a => a.City).HasColumnName("address_city").IsRequired();
p.Property(a => a.PostalCode).HasColumnName("address_postal_code").IsRequired();
p.Property(a => a.State).HasColumnName("address_state").IsRequired();
p.Property(a => a.Country).HasColumnName("address_country").IsRequired();
p.IsRequired();
});
builder.Property(d => d.DivisionId).HasColumnName("division_id").IsRequired();
builder.Ignore(d => d.Positions);
builder.Ignore(d => d.EmployeeAssignments);
builder.Ignore(d => d.EmployeeRoles);
builder.Ignore(d => d.Division);
//builder.HasMany(d => d.Positions).WithOne().HasForeignKey(d => d.DepartmentId).OnDelete(DeleteBehavior.Cascade);
//builder.HasMany(d => d.EmployeeAssignments).WithOne(e => e.Department).HasForeignKey(a => a.DepartmentId).OnDelete(DeleteBehavior.Cascade);
//builder.HasMany(d => d.EmployeeRoles).WithMany().UsingEntity<DepartmentRole>();
//builder.HasOne(d => d.Division).WithMany().HasForeignKey(d => d.DivisionId);
I have tried out a bunch of things such as removing the required
keyword or using a class instead of a record for the address and stuff like that. From my experience nothing I do here should cause the configuration to fail. However if I ignore the address property and comment out the ComplexProperty
mapping no problems arise. The closest post I have found to this is this issue, but that seems to be part of the EF core backlog now.
I have also tried to decompile and debug the EF core code responsible for this according to the stacktrace but I fear my inseniority made me not come to any conclusions.
My question is: Are there any obvious blunders in my attempts or does this seem like a EF core bug?