bchavez / Bogus

:card_index: A simple fake data generator for C#, F#, and VB.NET. Based on and ported from the famed faker.js.
Other
8.48k stars 480 forks source link

Bogus database seeding fails on .NET 6 #441

Open henry-js opened 1 year ago

henry-js commented 1 year ago

Version Information

Software Version(s)
Bogus NuGet Package 34.0.2
.NET Core? 6
.NET Full Framework? N/A
Windows OS? 11
Linux OS? N/A
Visual Studio? Code

What locale are you using with Bogus?

en

What is the expected behaviour?

Running the commands in EFCoreSeedDb example should successfully create the InitialCreate migration.

What is the actual behaviour?

Build succeeds and then fails due to a System.InvalidOperationException

Please provide a stack trace.

┌ jhenry@jhenry-dt  EFCoreSeedDb   master ≡ ~2 
└ $ dotnet ef migrations add InitialCreate
Build started...
Build succeeded.
System.InvalidOperationException: The seed entity for entity type 'Blog' cannot be added because another seed entity with the key value 'BlogId:1' has already been added.
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateData(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 Microsoft.EntityFrameworkCore.Sqlite.Infrastructure.Internal.SqliteModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
   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_DesignTimeModel()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.DesignTimeModel.get_Model()
   at Microsoft.EntityFrameworkCore.Design.DesignTimeServiceCollectionExtensions.<>c__DisplayClass1_0.<AddDbContextDesignTimeServices>b__10(IServiceProvider _)
   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 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.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.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)
The seed entity for entity type 'Blog' cannot be added because another seed entity with the key value 'BlogId:1' has already been added.

Any possible solutions?

EF Core team have stated that OnModelCreating now gets called twice In my own code I added a simple check to make sure the count of Blogs was not greater than the FakeData.Init(Count)

      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
         base.OnModelCreating(modelBuilder);

         const int Count = 10;

         FakeData.Init(Count);
         if (FakeData.Blogs.Count <= Count)
         {
         modelBuilder.Entity<Blog>().HasData(FakeData.Blogs);
         modelBuilder.Entity<Post>().HasData(FakeData.Posts);
         }
      }

This allows the migration to be built, but the HasData() method is never called, creating only empty tables when dotnet ef database update is called

How do you reproduce the issue?

Clone the repo and update all package references to .NET 6

Do you have a unit test that can demonstrate the bug?

No

Can you identify the location in Bogus' source code where the problem exists?

If the bug is confirmed, would you be willing to submit a PR?

Yes or No?

memtech3 commented 2 months ago

I'm running into the same issue. I tried using a try catch to ignore the exception but that hasn't helped. When I manually pass in a hand created entity in HasData() the migration succeeds and the entity gets added to the database. Has anyone figured out a solution to this?

I'm using Dotnet, EFCore, and dotnet-ef version 8

bchavez commented 2 months ago

@memtech3 could you check if these EF Core examples help?

I was recently on "On .NET Live" and gave a demo of Bogus working in latest EF Core here:

Let me know if that helps. I might need to update the .NET 6 EF core example in the repo if OnModelCreating is getting called twice.

memtech3 commented 2 months ago

Thanks! I'm finishing up a rough semester so I'll try to parse through that example when I get a chance to.

I used a Console.WriteLine() to verify that onModelCreated is in fact being called twice.

The project I'm working on is open source so if you'd like to take a look before I get a chance to here's the link to the repo: https://github.com/memtech3/dispatchsystem look on the database seeding branch

memtech3 commented 2 months ago

Looks like it had something to do with the way I implemented and called my bogus FakeData class...

Here's the commit that resolved my issues: https://github.com/memtech3/dispatchSystem/pull/8/commits/1ef1a382ad83c0c3761736d9ca0f107a80691414

Feel free to copy code to use as examples for documentation