升级到ASP.NET Core 2.0后无法创建迁移

时间:2017-08-20 13:01:10

标签: c# asp.net-core asp.net-core-mvc entity-framework-core asp.net-core-2.0

升级到ASP.NET Core 2.0后,我似乎无法再创建迁移。

我正在

  

“在类上调用方法'BuildWebHost'时发生错误   '程序'。继续没有应用程序服务提供商。错误:   发生了一个或多个错误。 (无法打开请求的数据库“...”   登录。登录失败。用户'...'“

登录失败

  

“无法创建'MyContext'类型的对象。添加实现   'IDesignTimeDbContextFactory'到项目中,或者看看   https://go.microsoft.com/fwlink/?linkid=851728了解其他模式   在设计时支持。“

我之前运行的命令是$ dotnet ef migrations add InitialCreate --startup-project "..\Web"(来自带有DBContext的项目/文件夹)。

连接字符串:"Server=(localdb)\\mssqllocaldb;Database=database;Trusted_Connection=True;MultipleActiveResultSets=true"

这是我的Program.cs

 public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
       WebHost.CreateDefaultBuilder(args)
           .UseStartup<Startup>()
           .Build();
}

30 个答案:

答案 0 :(得分:78)

您可以在Web项目中添加一个实现IDesignTimeDbContextFactory的类。

以下是示例代码:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<CodingBlastDbContext>
{
    public CodingBlastDbContext CreateDbContext(string[] args)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
        var builder = new DbContextOptionsBuilder<CodingBlastDbContext>();
        var connectionString = configuration.GetConnectionString("DefaultConnection");
        builder.UseSqlServer(connectionString);
        return new CodingBlastDbContext(builder.Options);
    }
}

然后,导航到您的数据库项目并从命令行运行以下命令:

dotnet ef migrations add InitialMigration -s ../Web/

dotnet ef database update -s ../Web/

-s stands for startup project and ../Web/ is the location of my web/startup project.

resource

答案 1 :(得分:32)

不需要IDesignTimeDbContextFactory

运行

add-migration initial -verbose

显示下的详细信息

  

在类“ Program”上访问IWebHost时发生错误。没有应用程序服务提供商就继续进行。

警告,这是问题的根本原因。

就我而言,问题在于,ApplicationRole : IdentityRole<int>并调用services.AddIdentity<ApplicationUser, IdentityRole>()导致出现以下错误

System.ArgumentException: GenericArguments[1], 'Microsoft.AspNetCore.Identity.IdentityRole', 
on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[TUser,TRole,TContext,
TKey,TUserClaim,TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type 'TRole'.
---> System.TypeLoadException: GenericArguments[1], 'Microsoft.AspNetCore.Identity.IdentityRole', 
on 'Microsoft.AspNetCore.Identity.UserStoreBase`8[TUser,TRole,TKey,TUserClaim,
TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type parameter 'TRole'.

答案 2 :(得分:6)

更好的解决方案:

如果您的启动项目是ASP.NET Core应用,则工具会尝试从应用程序的服务提供商处获取DbContext对象。

该工具首先尝试通过调用Program.BuildWebHost()并访问IWebHost.Services属性来获取服务提供者。

在Program.cs中的Main Method之后添加此方法

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build();

更新.net core 2.2

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
} 

其他可能的解决方案

确保您向依赖注入添加了Dbcontext:  AddDbContext<TContext>将使您的DbContext类型TContext和相应的DbContextOptions<TContext>可用于从服务容器中注入。 这需要在接受DbContext的{​​{1}}类型中添加构造函数参数。

实施例: 在Startup.cs

DbContextOptions<TContext>

AppDbContext代码:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
}

答案 3 :(得分:6)

就我而言,问题的原因是多个启动项目。我的解决方案中有三个项目:Mvc,Api和Dal。 Db项目中的DbContext和迁移。

我已经配置了多个启动项目。当我单击开始时,Mvc和Api项目都在运行。但是在这种情况下,我遇到了这个错误。

  

“无法创建类型为'MyContext'的对象。添加一个实现   项目的“ IDesignTimeDbContextFactory”的名称或查看   https://go.microsoft.com/fwlink/?linkid=851728了解其他模式   在设计时受支持。”

在将Mvc设置为唯一的启动项目并在Package Manager控制台中选择Dal之后,我可以成功添加迁移。

答案 4 :(得分:5)

在除AppContext类之外的AppContext.cs中添加另一个类:

// required when local database 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);
    }
}

这将解决您的第二个问题:

  

&#34;无法创建类型为&#39; MyContext&#39;的对象。添加&#39; IDesignTimeDbContextFactory&#39;的实现到项目,

之后,您将能够 add-migration Initial 并通过运行 update-database 命令执行它。 但是,如果在本地SqlServer中没有DataBase时运行这些命令,您将收到类似第一个错误的警告:&#34;错误

  调用方法&#39; BuildWebHost&#39;时发生

课堂&#39;节目&#39; ...   登录失败。用户&#39; ...&#39;&#34;

的登录失败

但这不是错误,因为将创建迁移并且可以执行迁移。 所以只是第一次忽略这个错误,后者因为Db将存在它不会再次发生。

答案 5 :(得分:4)

真正帮助我的是本文:https://elanderson.net/2017/09/unable-to-create-an-object-of-type-applicationdbcontext-add-an-implementation-of-idesigntimedbcontextfactory/

基本思想是,在从.net核心1到2的转换中,所有数据库初始化都应该从StartUp.cs移出到Program.cs中。否则,EF任务会在执行任务时尝试运行数据库。

“官方迁移文档中有一个很好的部分(https://docs.microsoft.com/en-us/ef/core/miscellaneous/1x-2x-upgrade)标题为”移动数据库初始化代码“,我似乎已经错过了。所以在你像我之前的任何一个兔子洞那样确保这不是是什么导致你需要添加IdesignTimeDbContextFactory的实现。“

答案 6 :(得分:3)

您可以从this discussion尝试此解决方案,该解决方案受到启发by this post

public static IWebHost MigrateDatabase(this IWebHost webHost)
{
    using (var scope = webHost.Services.CreateScope())
    {
        var services = scope.ServiceProvider;

        try
        {
            var db = services.GetRequiredService<MyContext>();
            db.Database.Migrate();
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while migrating the database.");
        }
    }

    return webHost;
}
public static void Main(string[] args)
{
    BuildWebHost(args)
        .MigrateDatabase()
        .Run();
}

答案 7 :(得分:3)

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost(args).Run();
    }

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .Build();
    }
}

只需将BuildWebHost()重命名为CreateWebHostBuilder(),因为迁移默认情况下使用此方法。

答案 8 :(得分:3)

我遇到了这个问题,并通过设置-> Web应用程序(包括Program.cs)项目解决了->“设置为启动项目”

然后运行-> add-migration initial -verbose

在程序包管理器控制台中

Set as Startup Project

答案 9 :(得分:3)

请确认您有参考资料

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />

答案 10 :(得分:2)

在我的情况下,我遇到了问题,因为我在 Startup.cs 文件中调用了名为 SeedData.EnsurePopulated()的方法。

public class Startup
{
    public Startup(IConfiguration configuration) => Configuration = configuration;
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        //
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseDeveloperExceptionPage();
        app.UseStatusCodePages();
        app.UseStaticFiles();
        app.UseSession();
        app.UseMvc(routes =>
        {
            //
        });

        SeedData.EnsurePopulated(app);
    }
}

SeedData 类的工作是将初始数据添加到数据库表中。它的代码是:

public static void EnsurePopulated(IApplicationBuilder app)
    {
        ApplicationDbContext context = app.ApplicationServices.GetRequiredService<ApplicationDbContext>();
        context.Database.Migrate();
        if (!context.Products.Any())
        {
            context.Products.AddRange(
            new Product
            {
                Name = "Kayak",
                Description = "A boat for one person",
                Category = "Watersports",
                Price = 275
            },
            ....
            );
            context.SaveChanges();
        }
    }

<强>解

在进行迁移之前,只需在Startup.cs文件中注释掉 SeedData 类的调用。

// SeedData.EnsurePopulated(app);

这解决了我的问题,希望你的问题也能以同样的方式解决。

答案 11 :(得分:2)

来自

https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation

  

创建新的ASP.NET Core 2.0应用程序时,此钩子是   默认情况下包括在内。在早期版本的EF Core和ASP.NET Core中,   该工具尝试直接调用Startup.ConfigureServices以便   获取应用程序的服务提供商,但是这种模式不再   在ASP.NET Core 2.0应用程序中正常工作。如果您要升级   一个ASP.NET Core 1.x应用程序到2.0,您可以修改您的程序   类以遵循新模式。

在.Net Core 2.x中添加工厂

public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
    {
        public BloggingContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }

答案 12 :(得分:2)

我遇到了错误

“无法创建类型为'MyContext'的对象。向项目中添加'IDesignTimeDbContextFactory'的实现,或在设计时支持https://go.microsoft.com/fwlink/?linkid=851728的其他模式。“ < / p>

这是解决我的问题的方式。在解决方案目录中运行以下命令

 dotnet ef migrations add InitialMigration --project "Blog.Infrastructure" --startup-project "Blog.Appication"

这里“应用程序”是我的包含Startup.cs类的启动项目,而“基础结构”是我的包含DbContext类的项目。

然后使用相同的结构运行更新。

dotnet ef database update --project "Blog.Infrastructure" --startup-project "Blog.Application"

答案 13 :(得分:2)

从2.0中的Startup.Configure开始播放数据库存在问题...你仍然可以通过这种方法来完成它。经过测试和工作正常

https://garywoodfine.com/how-to-seed-your-ef-core-database/

答案 14 :(得分:2)

以前,您在Startup.cs中的Configure方法中配置了种子数据。现在建议您仅使用Configure方法设置请求管道。应用程序启动代码属于Main方法。

重构的Main方法。将以下引用添加到Program.cs:

使用Microsoft.Extensions.DependencyInjection;

使用MyProject.MyDbContextFolder;

&#13;
&#13;
public static void Main(string[] args)
{
    var host = BuildWebHost(args);

    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<MyDbConext>();
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while seeding the database.");
        }
    }

    host.Run();
}
&#13;
&#13;
&#13;

答案 15 :(得分:2)

如果要避免这些IDesignTimeDbContextFactory问题:只需确保在启动时不使用任何Seed方法。我在启动时使用了静态种子方法,这对我造成了此错误。

答案 16 :(得分:1)

首先,请确保您已在prefix=/home/myusr/xcompiled-root/ exe_prefix= libdir=/lib includedir=/include ... 中配置了数据库 就我而言,由于没有在Startup.cs

中指定以下内容,因此出现了此错误
Startup.cs

答案 17 :(得分:1)

我遇到了同样的问题。我在解决方案中有两个项目。

  
      
  1. API
  2.   
  3. 具有上下文模型的服务和仓库
  4.   

最初,API项目被设置为Startup项目。

我将启动项目更改为包含上下文类的项目。 如果您使用的是 Visual Studio ,则可以通过以下方式将项目设置为“启动项目”:

  

打开解决方案资源管理器>>右键单击上下文项目>>选择“设置为启动项目”

答案 18 :(得分:0)

您还可以在启动类构造函数中使用json文件(连接字符串所在的位置)添加到配置中。示例:

keepDirtyOnReinitialize: true,
updateUnregisteredFields: true,

答案 19 :(得分:0)

如果context类在另一个类库项目中,出现这个错误,把命令行默认项目改成context项目,把解决方案启动项目设置为主API/ASP.net核心项目(你的DI容器在那里) ,然后重新运行命令 似乎 ef 核心工具包中报告了此错误 https://github.com/dotnet/efcore/issues/23957https://github.com/dotnet/efcore/issues/23853

答案 20 :(得分:0)

Manzur Alahi是正确的!我正在尝试学习JetBrains的Rider,当我尝试在Cmd,PowerShell等中使用dotnet-ef migrations add ...时遇到了相同的错误,但是当我使用Visual Studio IDE时没有问题。

我通过以下方式解决了该错误:

dotnet ef migrations add InitialMigration --project "Domain.Entities" --startup-project "WebApi"

这将更新数据库

dotnet ef database update --project "Domain.Entities" --startup-project "WebApi"

就像曼祖尔·阿拉希所说的那样。

答案 21 :(得分:0)

就我而言,在init中设置StartUp项目会有所帮助。您可以通过执行

dotnet ef migrations add init -s ../StartUpProjectName

答案 22 :(得分:0)

对我来说,问题是我在错误的项目中运行了迁移命令。在包含Startup.cs的项目中运行命令,而不是在包含DbContext的项目中运行命令使我能够克服这个特定问题。

答案 23 :(得分:0)

我在具有以下解决方案的解决方案中遇到了这个问题:

  • .NET Core 2.2 MVC项目
  • .NET Core 3.0 Blazor项目
  • .NET Standard 2.0类库项目中的数据库上下文

当Blazor项目设置为启动项目时,出现“无法创建对象...”消息,但如果将MVC项目设置为启动项目,则没有消息。

这让我感到困惑,因为在Package Manager Console(我正在创建迁移的地方)中,我将Default项目设置为实际上包含DB Context的C#类库,并且我还指定了我在对add-migration add-migration MigrationName -context ContextName的调用中具有数据库上下文,因此Visual Studio关心当前设置的启动项目似乎很奇怪。

我猜测原因是当Blazor项目是启动项目时,PMC正在从启动项目中确定.NET的版本为Core 3.0,然后尝试使用该版本在.NET上运行迁移标准2.0类库并遇到某种冲突。

无论是什么原因,将启动项目更改为针对Core 2.2的MVC项目,而不是Blazor项目,都可以解决此问题

答案 24 :(得分:0)

对我来说是因为我将启动项目的Output TypeConsole Application更改为Class Library

恢复为Console Application可以解决问题。

答案 25 :(得分:0)

.net核心控制台应用程序的示例数据库上下文类

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System.IO;

namespace EmailServerConsole.Data
{
    public class EmailDBContext : DbContext
    {
        public EmailDBContext(DbContextOptions<EmailDBContext> options) : base(options) { }
        public DbSet<EmailQueue> EmailsQueue { get; set; }
    }

    public class ApplicationContextDbFactory : IDesignTimeDbContextFactory<EmailDBContext>
    {
        EmailDBContext IDesignTimeDbContextFactory<EmailDBContext>.CreateDbContext(string[] args)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();
            var builder = new DbContextOptionsBuilder<EmailDBContext>();
            var connectionString = configuration.GetConnectionString("connection_string");
            builder.UseSqlServer(connectionString);
            return new EmailDBContext(builder.Options);
        }
    }
}

答案 26 :(得分:0)

在主项目的appsettings.json文件中,我已将“复制到输出目录”设置为“始终复制”,并且有效。

答案 27 :(得分:0)

自从我提到旧版以来,我遇到了同样的问题 - Microsoft.EntityFrameworkCore.Tools.DotNet

<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />

升级到新版本后,它已解决

答案 28 :(得分:-1)

在我的情况下,由于我从一些设计模式中删除了ConfigureServices中的MyDbContext,因此发生了此错误。检查一下。在Startup.cs =&gt; ConfigureServices添加以下行:

var connectionString = "Application Connection String!!!";
services.AddDbContext<MyDbContext>(c => c.UseSqlServer(connectionString));

答案 29 :(得分:-1)

我有同样的问题。刚刚将ap.jason更改为application.jason并解决了问题