-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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 3.1 Add-Migration failing to create new migration with -StartupProject, but EF 2.2 works #19760
Comments
Are you using .NET Framework on 2.2 and .NET Core on 3.1? We need a hook (issue dotnet/runtime#931) to make App.config work on .NET Core. Consider using Microsoft.Extensions.Configuration instead. |
I'm just trying to understand why does EF 2.2 work fine but EF 3.1 doesn't. What changed? Only the EF version changed so no reason it should change unless something about the EF tools changed that no longer works with ConfigurationManager. This is how I currently read the connection string.
I tried to change it to
Getting a different error now.... System.FormatException: A duplicate key 'appSettings:add:key' was found. |
@bricelam I appreciate your suggestion but it has it's own issues. I would like to know why Add-Migration is different, meaning that ConfigurationManager is not initialized?, in EF Core 3.1 vs EF Core 2.2. Here is my solution.
|
Hi @BobbyCannon I'm using the dotnet tools to do this kind of stuff.
I'm able to generate and run the migrations, without problems.
This should grab the SpeedyWebsite connection string from your website configuration. Can you try this? I'd be amazed if it wouldn't work for you... |
@MintPlayer I need to know how you created the variable "configuration" so I can attempt to reproduce your results. Also my migrations are stored in a different location than my website. Maybe this is why it works for you and not me.
Also note, I'm using the "Package Manager Console" inside Visual Studio (full version, not code). |
Hi, My migrations are also stored in my Data project ( The configuration variable is simply injected in the DbContext:
|
@MintPlayer I think you may have miss a critical part of my issue.
I can read configuration from an "AppSettings.json" but not from an "app/web.config" file from a .NET 4.7.2 Web Application and / or WPF application. The problem is that something changed between EF Core 2.2 to 3.1 that has broken or prevented ConfigurationManager from initializing properly. Now we must take extra steps to open the configuration for app.config and web.config. |
I'm sorry, I have no experience with the https://www.nuget.org/packages/System.Configuration.ConfigurationManager you're refering to. What limitations are you experiencing with https://www.nuget.org/packages/Microsoft.Extensions.Configuration? |
@BobbyCannon In trying to figure out what changed from 2.2 to 3.1, the first thing to rule out is whether or not you also changed from .NET Framework to .NET Core. The behavior you are seeing is expected on .NET Core. If you're still on .NET Framework then we will investigate more. |
@ajcvickers I'm only using .NET 4.7.2 (full framework) with EF 2.2 and EF 3.1 libraries. Details from the original post below: Further technical details |
@BobbyCannon @ajcvickers @bricelam I've found exactly the same problem with EF Core 3.1.3 and .NET Framework 4.8 (no .NET Core involved). The applications themselves work fine with EF Core 3.1.3; it's only the migrations that don't seem to. The first result I found from Googling was https://docs.microsoft.com/answers/questions/20091/wpf-core-connection-strings-inside-appconfig-not-w.html , so I made sure that my Startup Project was creating the exe.config file, and still get the same result. Thanks for your temporary workaround code @BobbyCannon! In the output below, the line
is because I added Presumably it's just falling back to a default. And the exception at the end is because Further technical details Output from PM> Add-Migration InitialCreate |
I feel this will not be fixed as future focus is on .NET Core. I do wish there were better .NET FX validation as this worked in EF Core 2.2. However I guess this will be another reason to encourage us to move to .NET Core. I do feel for those who cannot due to time and effort. |
We have experienced the exact same problem as @BobbyCannon |
/cc @bricelam |
It looks like we have two options for fixing this:
WorkaroundDon't use ConfigurationManager at design time. You could load and parse the XML file yourself or switch to something like Microsoft.Extensions.Configuration. |
Crazy idea: We could also call some internal code in ef.exe to get .NET Framework working again. |
WorkaroundYou can work around this issue by adding an implementation of class MyDesignTimeContextFactory : IDesignTimeDbContextFactory<MyContext>
{
public MyContext CreateDbContext(string[] args)
{
// Work around dotnet/efcore#19760
var startupAssembly = Assembly.Load("MyApp"); // TODO: Update this
AppDomain.CurrentDomain.SetData(
"APP_CONFIG_FILE",
new Uri(startupAssembly.CodeBase).LocalPath + ".config");
typeof(ConfigurationManager)
.GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, 0);
typeof(ConfigurationManager)
.GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, null);
typeof(ConfigurationManager).Assembly
.GetType("System.Configuration.ClientConfigPaths")
.GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, null);
return new MyContext();
}
} |
EDIT: The underlying issue causing this bug (dotnet/runtime#931) has been fixed in .NET 6 (relevant PR: dotnet/runtime#56748), making the workaround below unnecessary if you update to .NET 6. This workaround may also be useful for anyone porting an application from .NET Framework to .NET Core and isn't ready to switch to It is mostly the same as the previous suggestion, but instead of setting class MyDesignTimeContextFactory : IDesignTimeDbContextFactory<MyContext>
{
public MyContext CreateDbContext(string[] args)
{
// Copy the app config file to the expected location (i.e. "ef.dll.config")
// See: https://github.com/dotnet/corefx/blob/v3.1.9/src/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs#L63
var mainProjectAssembly = Assembly.Load("MyApp"); // TODO: Update this
string mainProjectConfigPath = new Uri(mainProjectAssembly.CodeBase).LocalPath + ".config";
var entryAssembly = Assembly.GetEntryAssembly();
string newConfigPath = new Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, entryAssembly.ManifestModule.Name)).LocalPath + ".config";
File.Copy(mainProjectConfigPath, newConfigPath, overwrite: true);
// Reset the configuration system
typeof(ConfigurationManager)
.GetField("s_initState", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, 0);
typeof(ConfigurationManager)
.GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, null);
typeof(ConfigurationManager).Assembly
.GetType("System.Configuration.ClientConfigPaths")
.GetField("s_current", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, null);
return new MyContext();
}
} |
I'm currently upgrading my project Speedy from EF core 2.2 to 3.1. The command below works fine on 2.2 but fails on 3.1.
Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose
In the Speedy repository https://github.com/BobbyCannon/Speedy there are two master branches.
Steps to reproduce
The code below returns null when using EF Core 3.1 but returns the connection string in the web.config of Speedy.Website.
Both projects reference System.Configuration.ConfigurationManager 4.7.0 nuget package to access the connection string in the web.config.
Further technical details
EF Core version: 2.2, 3.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET FX 4.7.2
Operating system: Windows 10
IDE: Visual Studio 2019 16.4
Output for EF Core 2.2
PM> Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose
Using project 'Speedy.Website.Data.Sql'.
Using startup project 'Speedy.Website'.
Build started...
Build succeeded.
C:\Workspaces\GitHub\Speedy - Core 2.2\packages\Microsoft.EntityFrameworkCore.Tools.2.2.6\tools\net461\any\ef.exe migrations add Initial --json --verbose --no-color --prefix-output --assembly "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.Data.Sql.dll" --startup-assembly "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.dll" --project-dir "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\" --language C# --working-dir "C:\Workspaces\GitHub\Speedy - Core 2.2" --data-dir "C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\App_Data" --root-namespace Speedy.Website.Data.Sql
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql'.
Using configuration file 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\bin\Speedy.Website.dll.config'.
Using data directory 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website\App_Data'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding IWebHost accessor...
No entry point was found for assembly 'Speedy.Website'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ContosoSqlDatabase'.
Using context 'ContosoSqlDatabase'.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.SqlServer'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.SqlServer'.
Finding design-time services referenced by assembly 'Speedy.Website'.
No referenced design-time services were found.
Finding IDesignTimeServices implementations in assembly 'Speedy.Website'...
No design-time services were found.
DetectChanges starting for 'ContosoSqlDatabase'.
DetectChanges completed for 'ContosoSqlDatabase'.
Writing migration to 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\Migrations\20200131123936_Initial.cs'.
Writing model snapshot to 'C:\Workspaces\GitHub\Speedy - Core 2.2\Speedy.Website.Data.Sql\Migrations\ContosoSqlDatabaseModelSnapshot.cs'.
'ContosoSqlDatabase' disposed.
To undo this action, use Remove-Migration.
PM>
Output for EF Core 3.1
PM> Add-Migration Initial -Project Speedy.Website.Data.Sql -StartupProject Speedy.Website -Verbose
Using project 'Speedy.Website.Data.Sql'.
Using startup project 'Speedy.Website'.
Build started...
Build succeeded.
C:\Workspaces\GitHub\Speedy\packages\Microsoft.EntityFrameworkCore.Tools.3.1.1\tools\net461\any\ef.exe migrations add Initial --json --verbose --no-color --prefix-output --assembly C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.Data.Sql.dll --startup-assembly C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.dll --project-dir C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql\ --language C# --working-dir C:\Workspaces\GitHub\Speedy --data-dir C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data --root-namespace Speedy.Website.Data.Sql
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql'.
Using configuration file 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin\Speedy.Website.dll.config'.
Using data directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data'.
Using assembly 'Speedy.Website.Data.Sql'.
Using startup assembly 'Speedy.Website'.
Using application base 'C:\Workspaces\GitHub\Speedy\Speedy.Website\bin'.
Using working directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website'.
Using root namespace 'Speedy.Website.Data.Sql'.
Using project directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website.Data.Sql'.
Using data directory 'C:\Workspaces\GitHub\Speedy\Speedy.Website\App_Data'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ContosoSqlDatabase'.
**** Connection String:
The text was updated successfully, but these errors were encountered: