Я не уверен, что изменилось, но теперь я получаю сообщение об ошибке: " Тип сущности 'GroupSubscriber' требует определения первичного ключа. " Однако у меня определен составной ключ в конфигурации EF, которую я подтвердил, действительно выполняется. Кроме того, я могу создать миграцию и обновить базу данных, в результате чего БД имеет составной первичный ключ.
Проект веб-API успешно собирается и может работать, но когда я вызываю любой маршрут, я получаю эту ошибку, даже если у меня вообще нет доступа к этому объекту.
Как я уже говорил, все это прекрасно работает, но кажется, что когда я вызываю маршрут для чего-то не связанного, это дает мне эту ошибку. Странно то, что я получаю и другие ошибки с .HasConversion, который раньше работал, но теперь сделал. Я преодолел эти ошибки с помощью обходных путей, но не могу сделать обходной путь для составного ключа, так как не могу изменить схему БД.
Если вам интересно, вот полная ошибка, которую я получаю:
{
"error": [
"The entity type 'GroupSubscriber' requires a primary key to be defined."
],
"stackTrace": " at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(IModel model)\r\n at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model)\r\n at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model)\r\n at Microsoft.EntityFrameworkCore.Internal.SqlServerModelValidator.Validate(IModel model)\r\n at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ValidatingConvention.Apply(InternalModelBuilder modelBuilder)\r\n at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder)\r\n at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelBuilt(InternalModelBuilder modelBuilder)\r\n at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.Validate()\r\n at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()\r\n at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)\r\n at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.<>c__DisplayClass5_0.<GetModel>b__1()\r\n at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)\r\n at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)\r\n at System.Lazy`1.CreateValue()\r\n at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)\r\n at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()\r\n at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()\r\n at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_2(IServiceProvider p)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, ServiceProviderEngineScope scope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(IServiceCallSite callSite, TArgument argument)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)\r\n at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()\r\n at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()\r\n at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()\r\n at Microsoft.EntityFrameworkCore.DbContext.get_Model()\r\n at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityType()\r\n at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.get_EntityQueryable()\r\n at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.System.Linq.IQueryable.get_Provider()\r\n at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)\r\n at Application.Accounts.Queries.GetAll.GetAllAccountsQueryHandler.Handle(GetAllAccountsQuery request, CancellationToken cancellationToken) in C:\\Repos\\API\\Application\\Accounts\\Queries\\GetAll\\GetAllAccountsQueryHandler.cs:line 27\r\n at MediatR.Pipeline.RequestPostProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)\r\n at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)\r\n at m25.Application.Infrastructure.RequestPerformanceBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next) in C:\\Repos\\API\\Application\\Infrastructure\\RequestPerformanceBehavior.cs:line 25\r\n at MediatR.Pipeline.RequestPreProcessorBehavior`2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate`1 next)\r\n at WebApi.Controllers.AccountsController.Get() in C:\\Repos\\API\\WebApi\\Controllers\\AccountsController.cs:line 34\r\n at lambda_method(Closure , Object )\r\n at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()\r\n at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)\r\n at System.Threading.Tasks.ValueTask`1.get_Result()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()"
}
Я попытался переместить конфигурацию в функцию OnModelCreating вместо того, чтобы использовать отдельный класс, но безуспешно.
Я также подтвердил, что могу создать миграцию и обновить базу данных.
В случае, если это помогает, другие ошибки, с которыми я сталкивался, заключались в использовании HasConversion для преобразования ICollection в / из CSV, что также вызывало ошибки, но я обработал это в классе (боль, но работоспособна).
GroupSubscriber.cs
public class GroupSubscriber
{
public Guid SubscriberId { get; set; }
public Subscriber.Subscriber Subscriber { get; set; }
public Guid GroupId { get; set; }
public Group Group { get; set; }
public long ShardKey { get; set; }
public Guid AccountId { get; set; }
}
GroupSubscriberConfiguration.cs
public class GroupSubscriberConfiguration : IEntityTypeConfiguration<GroupSubscriber>
{
public void Configure(EntityTypeBuilder<GroupSubscriber> builder)
{
builder.ToTable("SubscriberList_Group_Subscriber");
builder.HasKey(gs => new { gs.GroupId, gs.SubscriberId });
builder.Property(e => e.ShardKey).IsRequired();
builder.HasOne(e => e.Subscriber)
.WithMany(s => s.GroupSubscribers)
.HasForeignKey(e => e.SubscriberId)
.HasConstraintName("FK_SubscriberListGroupSubscriber_Subscriber")
.OnDelete(DeleteBehavior.ClientSetNull);
builder.HasOne(e => e.Group)
.WithMany(g => g.GroupSubscribers)
.HasForeignKey(e => e.GroupId)
.HasConstraintName("FK_SubscriberListGroupSubscriber_Group");
}
}
DbContext.cs
//standard DB Context code above but here's the important part
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(DbContext).Assembly));
}
Я ожидаю, что смогу использовать Fluent API для настройки составного первичного ключа.