Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有需要数据库的迁移和服务?_C#_Entity Framework_Asp.net Core_Entity Framework Core - Fatal编程技术网

C# 是否有需要数据库的迁移和服务?

C# 是否有需要数据库的迁移和服务?,c#,entity-framework,asp.net-core,entity-framework-core,C#,Entity Framework,Asp.net Core,Entity Framework Core,如果迁移工具“dotnet ef database update”在创建数据库之前运行我的应用程序BuildWebHost,那么我如何构建一个需要访问数据库的服务,同时也使用迁移?试图配置需要数据库的服务时引发异常,因为数据库不存在,并导致迁移命令失败。因此,永远不会创建数据库 我正在使用asp.NETCore2和EFCore2 更具体地说,使用空白数据库运行“dotnet ef database update”失败,错误如下: 在类上调用方法“BuildWebHost”时出错 “程序”。在没有

如果迁移工具
“dotnet ef database update”
在创建数据库之前运行我的应用程序
BuildWebHost
,那么我如何构建一个需要访问数据库的服务,同时也使用迁移?试图配置需要数据库的服务时引发异常,因为数据库不存在,并导致迁移命令失败。因此,永远不会创建数据库

我正在使用asp.NETCore2和EFCore2

更具体地说,使用空白数据库运行
“dotnet ef database update”
失败,错误如下:

在类上调用方法“BuildWebHost”时出错 “程序”。在没有应用程序服务提供商的情况下继续。错误: 无法打开登录请求的数据库“MyDb”。登录失败。 用户“MYCOMPUTER\MYNAME”登录失败

之所以会出现这种情况,是因为我构建了一个由我的“MyDb”数据库支持的自定义配置提供程序(最终目标是使用自定义选项类绑定到该数据库),my program.cs如下所示:

 public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((builderContext, config) =>
                {
                    var tmpconfig = config.Build();
                    config.AddMyOptionsConfig(options => options.UseSqlServer(tmpconfig.GetConnectionString("My_Database")));
                })
            .UseStartup<Startup>()
            .Build();
公共静态IWebHost BuildWebHost(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((builderContext,config)=>
{
var tmpconfig=config.Build();
config.addMyOptionConfig(options=>options.UseSqlServer(tmpconfig.GetConnectionString(“My_数据库”));
})
.UseStartup()
.Build();
AddMyOptionConfig最终会运行:

  public class EFConfigProvider : ConfigurationProvider
    {
     [...]

        // Load config data from EF DB.
        public override void Load()
        {
            var builder = new DbContextOptionsBuilder<MyDbContext>();
            OptionsAction(builder);

            using (var dbContext = new MyDbContext(builder.Options))
            {    
                 // dbContext.Database.EnsureCreated(); // will cause first migration to fail
                 Data = !dbContext.ConfigurationValue.Any() // throws exception
                      ? CreateAndSaveDefaultValues(dbContext)
                      : dbContext.ConfigurationValue.ToDictionary(c => c.Id, c => c.Value);
公共类EFConfigProvider:ConfigurationProvider
{
[...]
//从EF DB加载配置数据。
公共覆盖无效负载()
{
var builder=new DbContextOptionsBuilder();
选择行动(承建商);
使用(var dbContext=newmydbcontext(builder.Options))
{    
//dbContext.Database.EnsureCreated();//将导致第一次迁移失败
Data=!dbContext.ConfigurationValue.Any()//引发异常
?CreateAndSaveDefaultValues(dbContext)
:dbContext.ConfigurationValue.ToDictionary(c=>c.Id,c=>c.Value);
它在试图访问数据库时抛出一个
SQLException
,因为数据库尚未创建

但是,如果我尝试使用
dbContext.Database.EnsureCreated()
,则初始迁移会失败,因为表已经存在。我想尝试
dbContext.Database.Migrate()
相反,作为初学者,我担心可能会对生产环境造成意外后果。因此,我更希望通过命令行工具控制迁移

基本上,问题似乎是
“dotnet ef database update”
在创建数据库之前运行应用程序启动-
BuildWebHost
,但是
BuildWebHost
中添加的自定义配置提供程序需要数据库已经存在


如何解决这个难题?

从某种意义上说,您已经创建了一个循环引用。在ASP.NET核心项目上运行迁移时,应用程序被初始化为实例化运行迁移所需的
DbContext
。这是因为EF核心中的
DbContext
现在需要
DbContextOptions
要注入的实例,这与在EF中执行操作的旧方法不同,在EF中,连接字符串名称(或实际的完整连接字符串)将直接在构造函数上定义

通常情况下,这会很好地工作,但是,正如您所注意到的,因为应用程序初始化本身需要一个已经存在的数据库,所以在迁移之前无法运行它。因此,您有两个选项:

  • 您可以尝试提取需要现有数据库的数据块。这可能很简单,只需将其包装在try-catch中并接受异常,也可能更复杂。由于迁移数据块不需要此特定功能,因此可以在该场景中安全地将其从应用程序初始化中排除

  • 您可以将上下文和实体移动到类库中,并实现,以满足构建要迁移的
    DbContext
    的能力。然后,您可以对该类库而不是ASP.NET核心项目运行迁移。这样就避免了必须初始化应用程序才能执行迁移的问题迁移


  • BuildWebHost
    (和
    Startup.Configure
    )不应用于应用程序启动逻辑。ASP.NET团队的指导是使用
    Program.Main

    到目前为止,我的解决方案是将支持自定义配置提供程序的实体移动到单独的dbContext中

    现在,可以在需要时通过
    mydboptioncontext.Database.EnsureCreated()
    创建表,而不影响迁移,因为它们基于主上下文(
    MyDbContext


    选项表不再参与迁移,但由于不太可能更改,因此不应该出现问题。另一个缺点是需要(由于有两个上下文)要显式指定
    dotnet ef
    命令行工具的上下文,请执行以下操作。

    我正在尝试将自定义选项类添加为服务。如何在
    BuildWebHost
    (和
    Startup.ConfigureServices
    之外添加服务?我看不出有什么方法可以做到这一点。你能添加服务,但让它变懒,这样它就不会运行在设计时失败的代码吗?它是一个内置的dotnet核心服务
    services.Configure(Configuration);
    ,但我很快就看到了。我怀疑数据库在
    IConfigurationBuilder.Build()之后就被击中了
    被调用,我假设这发生在启动之前。我喜欢wa