I have the following class in NET Core2.0 App.
// required when local database does not exist or was deleted
public class ToDoContextFactory : IDesignTimeDbContextFactory<AppContext>
{
public AppContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<AppContext>();
builder.UseSqlServer("Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true");
return new AppContext(builder.Options);
}
}
This is required in Core 2.0 with migration when Database does not exist and has to be created when you run update-database.
Unable to create migrations after upgrading to ASP.NET Core 2.0
I would like not having ConnectionString in 2 places(here and in appsettings.json) but only in .json so I have tried to replace
"Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true"
with
ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString
but it's not working, I'm getting null value.
UPDATE 1:
Just to note that adding explicitly .json is not necessery in Core 2 so the problem is not with the file.
https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/
UPDATE 2:
Also I am already using Configuration for sending ConnectionString from .json to Context:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
}
But I can not use this for ToDoContextFactory because it does not have Configuration, and ToDoContextFactory is used by migrations so the App is not running at all.
SOLUTION: Based on answer from @JRB I made it work like this:
public AppContext CreateDbContext(string[] args)
{
string projectPath = AppDomain.CurrentDomain.BaseDirectory.Split(new String[] { @"bin\" }, StringSplitOptions.None)[0];
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(projectPath)
.AddJsonFile("appsettings.json")
.Build();
string connectionString = configuration.GetConnectionString("DefaultConnection");
var builder = new DbContextOptionsBuilder<AppContext>();
builder.UseSqlServer(connectionString);
return new AppContext(builder.Options);
}
STEP 1: Include the following in OnConfiguring()
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
}
STEP 2: Create appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"
}
}
STEP 3: Hard copy appsettings.json to the correct directory
Hard copy appsettings.json.config to the directory specified in the AppDomain.CurrentDomain.BaseDirectory directory.
Use your debugger to find out which directory that is.
Assumption: you have already included package Microsoft.Extensions.Configuration.Json (get it from Nuget) in your project.
In ASPNET Core you do it in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}
where your connection is defined in appsettings.json
{
"ConnectionStrings": {
"BloggingDatabase": "..."
},
}
Example from MS docs
There is actually a default pattern that you can employ to achieve this result without having to implement IDesignTimeDbContextFactory
and do any config file copying.
It is detailed in this doc, which also discusses the other ways in which the framework will attempt to instantiate your DbContext
at design time.
Specifically, you leverage a new hook, in this case a static method of the form public static IWebHost BuildWebHost(string[] args)
. The documentation implies otherwise, but this method can live in whichever class houses your entry point (see src). Implementing this is part of the guidance in the 1.x to 2.x migration document and what's not completely obvious looking at the code is that the call to WebHost.CreateDefaultBuilder(args)
is, among other things, connecting your configuration in the default pattern that new projects start with. That's all you need to get the configuration to be used by the design time services like migrations.
Here's more detail on what's going on deep down in there:
While adding a migration, when the framework attempts to create your DbContext
, it first adds any IDesignTimeDbContextFactory
implementations it finds to a collection of factory methods that can be used to create your context, then it gets your configured services via the static hook discussed earlier and looks for any context types registered with a DbContextOptions
(which happens in your Startup.ConfigureServices
when you use AddDbContext
or AddDbContextPool
) and adds those factories. Finally, it looks through the assembly for any DbContext
derived classes and creates a factory method that just calls Activator.CreateInstance
as a final hail mary.
The order of precedence that the framework uses is the same as above. Thus, if you have IDesignTimeDbContextFactory
implemented, it will override the hook mentioned above. For most common scenarios though, you won't need IDesignTimeDbContextFactory
.
How about passing it as dp injection into that class? in ConfigureServices:
services.Configure<MyOptions>(Configuration);
create class to hold json strings:
public class MyOptions
{
public MyOptions()
{
}
public string Option1 { get; set; }
public string Option2 { get; set; }
}
Add strings to json file:
"option1": "somestring",
"option2": "someothersecretstring"
In classes that need these strings, pass in as constructor:
public class SomeClass
{
private readonly MyOptions _options;
public SomeClass(IOptions<MyOptions> options)
{
_options = options.Value;
}
public void UseStrings()
{
var option1 = _options.Option1;
var option2 = _options.Option2;
//code
}
}
You can also do this in ASP.NET Core 2 by defining the connection string in your appSettings.json
file. Then in your Startup.cs
you specify which connection string to use.
appSettings.json
{
"connectionStrings": {
"YourDBConnectionString": "Server=(localdb)\\mssqllocaldb;Database=YourDB;Trusted_Connection=True"
}
}
Startup.cs
public static IConfiguration Configuration { get; private set;}
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
var connectionString = Configuration["connectionStrings:YourDBConnectionString"];
services.AddDbContext<YourDbContext>(x => x.UseSqlServer(connectionString));
Add the following code into
startup.cs
file.public void ConfigureServices(IServiceCollection services) { string con = Configuration.GetConnectionString("DBConnection"); services.AddMvc(); GlobalProperties.DBConnection = con;//DBConnection is a user defined static property of GlobalProperties class }
Use
GlobalProperties.DBConnection
property inContext
class.protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseSqlServer(GlobalProperties.DBConnection); } }
I understand this has been marked as answered but I ran into a bit of a problem when I was working on a project where I have my EF Core Data Access Layer in a .DLL Project separated from the rest of my project, API, Auth and Web and mostly will like my other projects to reference this Data project. And I don't want to want to come into the Data project to change connection strings everytime.
STEP 1: Include this in the OnConfiguring Method
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
IConfigurationRoot configuration = new ConfigurationBuilder()
**.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))**
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile($"appsettings.{envName}.json", optional: false)
.Build();
optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
}
NOTE: .SetBasePath(Path.Combine(Directory.GetCurrentDirectory())) This will negate or invalidate the need to copy the file to a directory as ASP.NET CORE is smart enough to pick the the right file. Also the environment specified will pick right file when the building for Release or Production, assuming the Prod environment file is selected.
STEP 2: Create appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"
}
}
PLEASE: Referece: Microsoft.Extensions.Configuration
来源:https://stackoverflow.com/questions/45796776/get-connectionstring-from-appsettings-json-instead-of-being-hardcoded-in-net-co