Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF bundle seems to not be properly passing --connection parameter #27325

Closed
sparksterz opened this issue Jan 31, 2022 · 15 comments
Closed

EF bundle seems to not be properly passing --connection parameter #27325

sparksterz opened this issue Jan 31, 2022 · 15 comments

Comments

@sparksterz
Copy link

I'm seeing an unusual issue when trying to create a self contained EF Bundle (6.0.1) as part of my CI script. I'm using Bitbucket pipelines for this and generating a bundle against an empty PSQL server which is successful. Once I generate the bundles I'm attempting a sanity check to run all the migrations against this empty database and that's where I'm running into issues.

Here's how I'm effectively creating trying to test the bundle via my sh script

# Prep dotnet tool for installation
cat << \EOF >> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:/root/.dotnet/tools"
EOF
export PATH="$PATH:/root/.dotnet/tools"

# Install dotnet ef migration tool
dotnet tool install --global dotnet-ef

# Configuration is a bogus param to get around an open issue documented here:
# https://github.com/dotnet/efcore/issues/25555#issuecomment-1007891032
dotnet ef migrations bundle -p './src/Data/Data.csproj' -s './src/API/API.csproj' --configuration bundle --self-contained -r linux-x64

# Test migration against test DB
echo "Test execution of bundle against DB with connection string $TEST_DB_MIGRATION_CONNECTION"
./efbundle --connection "$TEST_DB_MIGRATION_CONNECTION"

This seems to succeed in bundle generation but not in executing the bundle against my test DB. Despite being a self contained bundle it seems that it's trying to use my application startup and my startup is failing to resolve the connection string for my server (I'll paste the full stack trace with verbose build at the end):

You can invoke the tool using the following command: dotnet-ef
Tool 'dotnet-ef' (version '6.0.1') was successfully installed.
Build started...
Build succeeded.
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 6.0.1 initialized 'MyContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL:6.0.2+854d2438884c0bf3a4ba8ccde2c47f7ba1ea3a4c' with options: MigrationsAssembly=Data 
Building bundle...
Done. Migrations Bundle: /opt/atlassian/pipelines/agent/build/efbundle
Don't forget to copy appsettings.json alongside your bundle if you need it to apply migrations.
Test execution of bundle against DB with connection string server=localhost;port=5432;username=test_user;database=pipelines;password=test_user_password;
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')

The code in my startup class I believe it's failing on is:

var connectionString = configuration.GetConnectionString("DefaultConnection");

services.AddDbContext<MyContext>(options =>
     options.UseNpgsql(connectionString, sqlOptions =>
     {
          sqlOptions.MigrationsAssembly("Data");
     }), ServiceLifetime.Transient);

Below is my build's stack trace:

Using project '/opt/atlassian/pipelines/agent/build/src/Data/Data.csproj'.
Using startup project '/opt/atlassian/pipelines/agent/build/src/API/API.csproj'.
Writing '/opt/atlassian/pipelines/agent/build/src/Data/obj/Data.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=/tmp/tmpZfHjww.tmp /verbosity:quiet /nologo /opt/atlassian/pipelines/agent/build/src/Data/Data.csproj
Writing '/opt/atlassian/pipelines/agent/build/src/API/obj/API.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=/tmp/tmp4DINNv.tmp;Configuration=bundle /verbosity:quiet /nologo /opt/atlassian/pipelines/agent/build/src/API/API.csproj
Build started...    
dotnet build /opt/atlassian/pipelines/agent/build/src/API/API.csproj --configuration bundle /verbosity:quiet /nologo
Build succeeded.
	0 Warning(s)
    0 Error(s)
Time Elapsed 00:00:03.57
Build succeeded.
dotnet exec --depsfile /opt/atlassian/pipelines/agent/build/src/API/bin/bundle/net6.0/API.deps.json --additionalprobingpath /root/.nuget/packages --runtimeconfig /opt/atlassian/pipelines/agent/build/src/API/bin/bundle/net6.0/API.runtimeconfig.json /root/.dotnet/tools/.store/dotnet-ef/6.0.1/dotnet-ef/6.0.1/tools/netcoreapp3.1/any/tools/netcoreapp2.0/any/ef.dll migrations bundle --self-contained -r linux-x64 --assembly /opt/atlassian/pipelines/agent/build/src/API/bin/bundle/net6.0/Data.dll --project /opt/atlassian/pipelines/agent/build/src/Data/Data.csproj --startup-assembly /opt/atlassian/pipelines/agent/build/src/API/bin/bundle/net6.0/API.dll --startup-project /opt/atlassian/pipelines/agent/build/src/API/API.csproj --project-dir /opt/atlassian/pipelines/agent/build/src/Data/ --root-namespace Data --language C# --framework net6.0 --configuration bundle --working-dir /opt/atlassian/pipelines/agent/build --verbose
Using assembly 'Data'.
Using startup assembly 'API'.
Using application base '/opt/atlassian/pipelines/agent/build/src/API/bin/bundle/net6.0'.
Using working directory '/opt/atlassian/pipelines/agent/build/src/API'.
Using root namespace 'Data'.
Using project directory '/opt/atlassian/pipelines/agent/build/src/Data/'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'API'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
Found DbContext 'MyContext'.
Finding DbContext classes in the project...
Using context 'MyContext'.
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 6.0.1 initialized 'MyContext' using provider 'Npgsql.EntityFrameworkCore.PostgreSQL:6.0.2+854d2438884c0bf3a4ba8ccde2c47f7ba1ea3a4c' with options: MigrationsAssembly=Data 
Building bundle...
dotnet publish --runtime linux-x64 --output /tmp/pngdgzmd.xez/publish --self-contained
Microsoft (R) Build Engine version 17.0.0+c9eb9dd64 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
  Determining projects to restore...
  Restored /opt/atlassian/pipelines/agent/build/src/Data.Core/Data.Core.csproj (in 1.76 sec).
  Restored /opt/atlassian/pipelines/agent/build/src/Services.Core/Services.Core.csproj (in 305 ms).
  Restored /opt/atlassian/pipelines/agent/build/src/Services/Services.csproj (in 2.1 sec).
  Restored /opt/atlassian/pipelines/agent/build/src/Models/Models.csproj (in 17 ms).
  Restored /opt/atlassian/pipelines/agent/build/src/Entities/Entities.csproj (in 20 ms).
  Restored /opt/atlassian/pipelines/agent/build/src/Data/Data.csproj (in 19 ms).
  Restored /opt/atlassian/pipelines/agent/build/src/API/API.csproj (in 2.14 sec).
  Restored /tmp/pngdgzmd.xez/efbundle.csproj (in 2.14 sec).
  Models -> /opt/atlassian/pipelines/agent/build/src/Models/bin/Debug/net6.0/Models.dll
  Entities -> /opt/atlassian/pipelines/agent/build/src/Entities/bin/Debug/net6.0/Entities.dll
  Data.Core -> /opt/atlassian/pipelines/agent/build/src/Data.Core/bin/Debug/net6.0/Data.Core.dll
  Services.Core -> /opt/atlassian/pipelines/agent/build/src/Services.Core/bin/Debug/net6.0/Services.Core.dll
  Data -> /opt/atlassian/pipelines/agent/build/src/Data/bin/Debug/net6.0/Data.dll
  Services -> /opt/atlassian/pipelines/agent/build/src/Services/bin/Debug/net6.0/Services.dll
/opt/atlassian/pipelines/agent/build/src/API/Controllers/CRMController.cs(112,63): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [/opt/atlassian/pipelines/agent/build/src/API/API.csproj]
  API -> /opt/atlassian/pipelines/agent/build/src/API/bin/Debug/net6.0/API.dll
  Models -> /opt/atlassian/pipelines/agent/build/src/Models/bin/Debug/net6.0/Models.dll
  Entities -> /opt/atlassian/pipelines/agent/build/src/Entities/bin/Debug/net6.0/Entities.dll
  Services.Core -> /opt/atlassian/pipelines/agent/build/src/Services.Core/bin/Debug/net6.0/Services.Core.dll
  Data.Core -> /opt/atlassian/pipelines/agent/build/src/Data.Core/bin/Debug/net6.0/Data.Core.dll
  Data -> /opt/atlassian/pipelines/agent/build/src/Data/bin/Debug/net6.0/Data.dll
  Services -> /opt/atlassian/pipelines/agent/build/src/Services/bin/Debug/net6.0/Services.dll
  efbundle -> /tmp/pngdgzmd.xez/bin/Debug/net6.0/linux-x64/efbundle.dll
  efbundle -> /tmp/pngdgzmd.xez/publish/
Done. Migrations Bundle: /opt/atlassian/pipelines/agent/build/efbundle
Don't forget to copy appsettings.json alongside your bundle if you need it to apply migrations.
Test execution of bundle against DB with connection string server=localhost;port=5432;username=test_user;database=pipelines;password=test_user_password;
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'API'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
   at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
   at Microsoft.EntityFrameworkCore.NpgsqlDbContextOptionsBuilderExtensions.UseNpgsql(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 npgsqlOptionsAction)
   at API.Startup.<>c__DisplayClass6_0.<ConfigureDatabase>b__0(DbContextOptionsBuilder options)
   at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_0`2.<AddDbContext>b__0(IServiceProvider p, DbContextOptionsBuilder b)
   at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action`2 optionsAction)
   at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass17_0`1.<AddCoreServices>b__0(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.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.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__17`1.<AddCoreServices>b__17_1(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.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, 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.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetServices[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextTypes()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextType(String name)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.ExecuteInternal(String[] args)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.<>c__DisplayClass6_0.<Configure>b__0(String[] args)
   at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.Execute(String context, Assembly assembly, Assembly startupAssembly, String[] args)
Value cannot be null. (Parameter 'connectionString')

EF Core version: 6.0.1
dotnet-ef version: 6.0.1
Database provider :Npgsql.EntityFrameworkCore.PostgreSQL:6.0.2+854d2438884c0bf3a4ba8ccde2c47f7ba1ea3a4c
Target framework: .Net 6
.Net Build image: mcr.microsoft.com/dotnet/sdk:6.0

@ajcvickers
Copy link
Member

/cc @bricelam I think this is by-design, but let's discuss in triage.

@sparksterz
Copy link
Author

/cc @bricelam I think this is by-design, but let's discuss in triage.

By design that it's tying into my startup project? I'm not above making a throwaway project to target just when building my EFBundle, but the fact that the connection string doesn't seem to be making it in suggests to me that my only viable approach may be to copy my appsettings.json and write my connection string straight to it rather than trying to pass it by variable.

@ajcvickers
Copy link
Member

Duplicate of #26869.

@sparksterz When --connection is used, EF still runs the normal configuration code to get a connection string, but then replaces it with the one passed with --connection. In addition, the connection string given to EF cannot be null. #26869 will change that, making this easier. As a workaround you can add a check for null in your code.

@sparksterz
Copy link
Author

Duplicate of #26869.

...As a workaround you can add a check for null in your code.

So...I'm a little unclear as to the direction here. If I have a null connection string in startup, due to attempting to run the efbundle, are you suggesting that I don't attempt to register the context?

Not knowing what the efbundle does in order to run the migrations I'm not sure if that's what you're recommending, or if you're saying I should follow the workflow in the linked bug and create an appsettings.json on the fly

@ajcvickers
Copy link
Member

@sparksterz

are you suggesting that I don't attempt to register the context?

I'm suggesting you register it with either no connection string or a dummy one, since it's going to be replaced anyway.

@sparksterz
Copy link
Author

Yeah...that sure solved it for anyone else looking. Thanks for the help

@colespencer1453
Copy link

@ajcvickers Hi I'm also encountering this issue. It is unclear to me what I need to do in order to execute the executable when passing the connection string. What variable is it looking for in the app settings file? Also how do I copy the app settings file into the bundle? Appreciate the help! Would love to see documentation around these issues exist in documentation somewhere!

@roji roji closed this as not planned Won't fix, can't repro, duplicate, stale Jul 7, 2022
@ajcvickers
Copy link
Member

@colespencer1453 Its taking the connection string from wherever your code takes it from. EF doesn't know anything about specific configuration files or mechanisms. To find out what this is, look for the code calling UseNpgsql, UseSqlServer, or similar.

@colespencer1453
Copy link

@ajcvickers I get the following output when running the below. When building the migration bundle I get the warning "Don't forget to copy appsettings.json alongside your bundle if you need it to apply migrations.". However, it isn't clear how to do that. My Program.cs file uses useNpgsql:
builder.Services.AddDbContext<DbContextInstance>(options => options.UseNpgsql(configuration["Postgres:DefaultConnection"]));

The appsettings files have this variable declared. I'm unclear what else I need to add to avoid the below error.

./efbundle --connection '{connectionString}'
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'Advertising.Api'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Using application service provider from Microsoft.Extensions.Hosting.
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
at Microsoft.EntityFrameworkCore.NpgsqlDbContextOptionsBuilderExtensions.UseNpgsql(DbContextOptionsBuilder optionsBuilder, String connectionString, Action1 npgsqlOptionsAction) at Program.<>c__DisplayClass0_0.<<Main>$>b__0(DbContextOptionsBuilder options) at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_02.b__0(IServiceProvider p, DbContextOptionsBuilder b)
at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action2 optionsAction) at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass17_01.b__0(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.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.CallSiteVisitor2.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.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.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__171.<AddCoreServices>b__17_1(IServiceProvider p) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.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.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.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.CallSiteVisitor2.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.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetServices[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextTypes() at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.FindContextType(String name) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType) at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.ExecuteInternal(String[] args) at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.<>c__DisplayClass6_0.<Configure>b__0(String[] args) at Microsoft.DotNet.Cli.CommandLine.CommandLineApplication.Execute(String[] args) at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsBundle.Execute(String context, Assembly assembly, Assembly startupAssembly, String[] args) Value cannot be null. (Parameter 'connectionString')

@colespencer1453
Copy link

@ajcvickers I eventually figured this one out. We have multiple projects with our migrations in one and startup host in the other. The appsettings file was in startup file, but I was running the efbundle executable from the migrations project.

My take away here is still that the documentation is very unclear on how to use migrations bundles especially in a CI/CD context. My suggestion would be to change the warning:

"Don't forget to copy appsettings.json alongside your bundle if you need it to apply migrations." output when creating a bundle to --> "Warning efbundle executable must be run in a directory with an appsettings.json file. Otherwise execution will fail."

Are you all still planning to not require the appsettings file to be present? Seems very strange to require a placeholder in appsettings when you are passing the connection string as an arguement.

@George2321
Copy link

@colespencer1453 could you please advise on how you made it work ? I also have multiple projects with the migrations in one and startup host in the other.

@colespencer1453
Copy link

@George2321 I wrote a small medium article about setting up migrations in an azure devops pipeline here:
https://medium.com/@css.csce1453/applying-ef-core-migrations-in-azure-devops-release-pipeline-postgresql-f9f4c8315e4a

The command to run the migration with split proejcts looks like

migrations bundle --project src/MigrationsProject --startup-project src/StartupProject

This has been working pretty well for me so far.

@George2321
Copy link

Thank you @colespencer1453, excellent article and work. I share your sentiment on there being a lack of documentation and it being impractical with the extra scripting and permissions required. I decided to go with the older method of using the ef core migrations script tool for now.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
@hazzinator1
Copy link

For anyone following @colespencer1453's guide, just a note that when running the bundle you need to cd into the directory with the efbundle.exe, as the bundle will look for the appsettings.json in your current working directory rather than the efbundle.exe execution directory. Tripped me up as I had the appsettings.json next to the efbundle.exe but couldn't work out why it kept coming up with missing configuration.

@andreasnett-in
Copy link

@George2321 I wrote a small medium article about setting up migrations in an azure devops pipeline here: https://medium.com/@css.csce1453/applying-ef-core-migrations-in-azure-devops-release-pipeline-postgresql-f9f4c8315e4a

The command to run the migration with split proejcts looks like

migrations bundle --project src/MigrationsProject --startup-project src/StartupProject

This has been working pretty well for me so far.

Thanks for your article, this is really helpful. However I am not able to execute the bundle myself in this way. I think it is because my Connection String is not of the correct format.
Would you be able to share what kind of Connection String you are using?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants