Here is an approach that might work for you.
If I run it in the folder of the shared project, it does not have access to the connection string specified in the startup.cs.
Startup.cs
I'm assuming that in your Startup.cs, you're specifying the connection string by accessing Configuration
rather than by hard coding it. Further, I'm assuming that in your Startup.cs file's constructor, you're setting up configuration from a few sources. In other words, your Startup.cs might look something like this:
public class Startup
{
public IConfiguration Config { get; set; }
public Startup(IHostingEnvironment env)
{
var config = new Configuration()
.AddJsonFile("config.json")
.AddUserSecrets()
.AddEnvironmentVariables();
Config = config;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<MyDbContext>(options =>
{
options.UseSqlServer(Config["ConnectionStrings:MyDbContext"]);
});
}
public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider)
{
var db = serviceProvider.GetRequiredService<MyDbContext>();
db.Database.AsSqlServer().EnsureCreated();
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
config.json
Further, I'm assuming that you're adding the connection string to a config.json in the root of your project (or that you adding it via user secrets or environmental variables.) Your config.json might look something like this:
{
"ConnectionStrings": {
"MyDbContext": "Some-Connection-String"
}
}
If you're not doing it that way, it might be worth trying it.
I have gleaned from questions like this that it does work from the shared project if you specify the connection string in the OnConfiguring method of the DbContext but I really would like to keep this code separate from the configuration.
DbContext
If my assumptions above are correct, then you can access the connection string in the DbContext
by using the same pattern that you used in the Startup
class. That is, in the DbContext
constructor, setup the IConfiguration
. Then, in OnConfiguring
, access the connection string. It might look something like this:
public class MyDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<SomeModel>().Key(e => e.Id);
base.OnModelCreating(builder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var connString = Config["ConnectionStrings:MyDbContext"];
optionsBuilder.UseSqlServer(connString);
}
public IConfiguration Config { get; set; }
public MyDbContext()
{
var config = new Configuration()
.AddJsonFile("config.json")
.AddEnvironmentVariables();
Config = config;
}
}
Project Structure
You'll of course need to have a config.json file in the root of your shared projects folder too. So, your projects' structure could look something like this:
SharedDataContext
Migrations
config.json
project.json
WebApp
config.json
project.json
Startup.cs
In the above, both config.json files contain a connection string setting for the DbContext
.
Some Thoughts
If you don't like duplicating the config.json connection string stuff, then you can use environmental variables or user secrets instead.