我正在使用Entityframework Core和代码优先方法建立一个新数据库。我已经在下面的代码清单中设置了一个上下文类,并且为数据库表设置了所有必需的类。 现在,我要使用
创建新数据库using (var context = new MyContext())
{
context.Database.EnsureCreated();
}
但是我得到一个错误,该连接字符串不能为null。
我的连接字符串在appsettings.json文件中设置,我在项目构建时将其复制到输出目录。
我尝试了几种不同的方法来从appsettings文件中获取连接字符串,但是所有方法都具有相同的结果。在Startup类的Configuration属性中,我可以看到appsettings文件已正确加载,但是当我想使用
获取字符串时ConnectionString = Configuration["Connectionstrings:MyConnection"];
ConnectionString始终为null。
我的Startup.cs文件中有此文件:
public class Startup
{
public static string ConnectionString { get; private set; }
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment _environment)
{
Configuration = new ConfigurationBuilder()
.SetBasePath(_environment.ContentRootPath)
.AddJsonFile("appsettings.json")
.Build();
}
在“配置-方法”中包含以下内容
using (var context = new MyContext())
{
context.Database.EnsureCreated();
}
在上下文类中,我有以下代码
public class MyContext : DbContext
{
public MyContext()
{
}
public static string GetConnectionString()
{
return Startup.ConnectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder _builder)
{
_builder.UseSqlServer(GetConnectionString());
}
因此,现在,当我启动应用程序时,在OnConfiguring-方法中出现错误,即连接字符串不能为空。
我的appsettings.json文件是
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"Connnectionstrings": {
"MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
},
}
答案 0 :(得分:4)
ConnectionString
始终为空,因为有错字,请尝试
ConnectionString = Configuration["Connnectionstrings:MyConnection"];
或在appsettings.json中修复名称
答案 1 :(得分:1)
我可以向您展示两个如何通过从appsettings.json
加载的强类型Settings类传递连接字符串的选项。对于这两种方式,您只需要将配置设置从默认的ConnnectionStrings
移到自定义部分,并完全控制数据库设置并将其传递给您EntityFramework
上下文。
您需要在Startup
类中进行此操作:
private Settings _settings;
public Startup(IConfiguration configuration, ...)
{
Configuration = configuration;
...
}
public IConfiguration Configuration { get; }
...
public void ConfigureServices(IServiceCollection services)
{
services
.AddOptions()
.Configure<Settings>(Configuration.GetSection("Settings"))
.AddSingleton(Configuration);
_settings = Configuration.GetSection(nameof(Settings)).Get<Settings>();
services.AddTransient<DesignTimeDbContextFactory>();
services.AddDbContext<MyContext>(options =>
{
if (_settings.DatabaseSettings.UseInMemory)
{
options.UseInMemoryDatabase("DummyInMemoryDatabase");
}
else
{
// Option 1
options.UseSqlServer(_settings.DatabaseSettings.BuildConnectionString());
// Option 2
options.UseSqlServer(_settings.ConnectionStrings.MyConnection);
}
});
...
}
这是相应的appsettings.json
文件:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"Settings": {
// Option 1: move connection strings to custom strong typed Settings class
"ConnnectionStrings": {
"MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
},
// Option 2: store DB settings any custom way you like - also to get via strong typed Settings class
"DatabaseSettings": {
"UseInMemory": false,
"Host": ".",
"Name": "MyDatabase",
"User": "qwerty",
"Password": "@#$%*"
}
}
}
强类型的设置类:
/// <summary> Represents settings configured in appsettings.json file </summary>
public class Settings
{
/// <summary> Option 1: move connection strings to custom strong typed Settings class </summary>
public Connections ConnectionStrings { get; set; }
/// <summary> Option 2: store DB settings any custom way you like - also to get via strong typed Settings class </summary>
public Database DatabaseSettings { get; set; }
}
public class Connections
{
public string MyConnection { get; set; }
}
public class Database
{
public bool UseInMemory { get; set; }
public string Host { get; set; }
public string Name { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string BuildConnectionString() => $"Server={Host};Database={Name};User Id={User};Password={Password}";
}
以及用于数据库迁移和其他设计时代码生成的辅助类-DesignTimeDbContextFactory
:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyContext>
{
public MyContext CreateDbContext(string[] args)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))
.AddJsonFile("appsettings.json", optional: false);
var config = builder.Build();
var settingsSection = config.GetSection("Settings");
var settings = new Settings();
settingsSection.Bind(settings);
var optionsBuilder = new DbContextOptionsBuilder<MyContext>()
.UseSqlServer(settings.ConnectionStrings.MyConnection); // or you can use option #2 either
return new MyContext(optionsBuilder.Options);
}
}
答案 2 :(得分:0)
以下模板采用了我从asp.net内核中窃取的模式。
{
"ConnectionStrings": {
"MyConnection": "Data Source=WithSqlite",
"YourConnection": "Server=(localdb)\\mssqllocaldb;Database=WithSqlServer;Trusted_Connection=True"
}
}
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
// DbSet goes here
}
static class Program
{
private static readonly IConfiguration _configuration;
static Program()
{
_configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
}
private static void ConfigureServices(IServiceCollection isc)
{
isc.AddSingleton(_configuration);
isc.AddDbContext<AppDbContext>(options =>
{
options.UseSqlite(_configuration["ConnectionStrings:MyConnection"]);
//options .UseSqlServer(_configuration.GetConnectionString("YourConnection"));
});
isc.AddSingleton<TheApp>();
}
public static ServiceProvider CreateServiceProvider()
{
// create service collection
IServiceCollection isc = new ServiceCollection();
ConfigureServices(isc);
// create service provider
return isc.BuildServiceProvider();
}
private static void Main(string[] args)
{
// create application instance and run
using (var scope = CreateServiceProvider().CreateScope())
{
scope.ServiceProvider.GetRequiredService<TheApp>().Run();
// It is said that GetRequiredService is much better than GetService.
}
}
}
class TheApp
{
private readonly AppDbContext _db;
public TheApp(AppDbContext db)
{
_db = db;
}
public void Run()
{
// Your main logic goes here
}
}
class MigrationHelper: IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args) =>
Program.CreateServiceProvider()
.CreateScope()
.ServiceProvider
.GetService<AppDbContext>();
}