c#-升级到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();
}
22个解决方案
72 votes

您可以在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.

资源

jaaso answered 2019-10-09T17:25:20Z
24 votes

不需要ApplicationRole : IdentityRole<int>

ApplicationRole : IdentityRole<int>

这将揭示下的细节

在类“ 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'.
tchelidze answered 2019-10-09T17:26:20Z
5 votes

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

// 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);
    }
}

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

“无法创建类型为'MyContext'的对象。将'IDesignTimeDbContextFactory'的实现添加到项目中,

之后,您将能够添加迁移初始值并通过运行update-database命令执行它。但是,如果在本地SqlServer中还没有数据库的情况下运行这些命令,则会收到类似第一个错误的警告:“一个错误

在类“程序”上调用方法“ BuildWebHost”时发生...   登录失败。 用户“ ...”的登录失败

但这不是错误,因为将创建迁移并可以执行迁移。因此,只需第一次忽略此错误,由于Db将存在,因此不会再次发生。

borisdj answered 2019-10-09T17:27:24Z
4 votes

这篇文章真正帮助了我:[https://elanderson.net/2017/09/unable-to-create-an-object-of-type-application-dbcontext-add-an-implementation-of-idesigntimedbcontextfactory/]

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

“官方迁移文档([https://docs.microsoft.com/en-us/ef/core/miscellaneous/1x-2x-upgrade]中有一个不错的部分,标题为“移动数据库初始化代码”,我似乎 因此,在像我一样努力解决任何麻烦之前,请确保这不是导致您需要添加IdesignTimeDbContextFactory实现的原因。”

Rtype answered 2019-10-09T17:28:04Z
4 votes

更好的解决方案:

如果您的启动项目是Program.BuildWebHost()应用程序,则这些工具会尝试从应用程序的服务提供商获取IWebHost.Services对象。

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

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

public static IWebHost BuildWebHost(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build();
Ali Bayat answered 2019-10-09T17:28:48Z
4 votes

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

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

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

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

Gürol Mehmet Cetin answered 2019-10-09T17:29:33Z
3 votes

请确认您有参考

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />
Vladmir answered 2019-10-09T17:29:59Z
3 votes

您可以从此讨论中尝试此解决方案,该讨论是受本文启发的。

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();
}
user2771704 answered 2019-10-09T17:30:24Z
2 votes

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

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

使用Microsoft.Extensions.DependencyInjection;

使用My Project.My DbContext文件夹;

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();
}

Miguel Torres C answered 2019-10-09T17:31:16Z
2 votes

从Startup.Configure在2.0中的ef播种db存在问题...您仍然可以通过此方法来解决。 经过测试并正常工作

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

Nick G. answered 2019-10-09T17:31:49Z
2 votes

就我而言,我遇到了问题,因为在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);

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

yogihosting answered 2019-10-09T17:32:37Z
2 votes

[https://docs.microsoft.com/zh-CN/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);
        }
    }
Anton Swanevelder answered 2019-10-09T17:33:18Z
2 votes

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

codeYouLaterBro answered 2019-10-09T17:33:43Z
1 votes

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

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

在Package Manager控制台中

设置为启动项目

Ali Ahmadi answered 2019-10-09T17:34:27Z
1 votes
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,因为,迁移默认情况下使用此方法

sherox answered 2019-10-09T17:34:53Z
0 votes

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

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

升级到较新版本后,它得到解决

vinayak hegde answered 2019-10-09T17:35:24Z
0 votes

在主项目的appsettings.json文件中,我已将“复制到输出目录”设置为“始终复制”,并且可以正常工作。

geet answered 2019-10-09T17:35:49Z
0 votes

.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);
        }
    }
}
Isanka Thalagala answered 2019-10-09T17:36:15Z
0 votes

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

AliAzra answered 2019-10-09T17:36:39Z
0 votes

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

    IConfigurationRoot _config;
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json");

        _config = builder.Build();
    }
Vio answered 2019-10-09T17:37:05Z
0 votes

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

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

Robouste answered 2019-10-09T17:37:38Z
-1 votes

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

var connectionString = "Application Connection String!!!";
services.AddDbContext<MyDbContext>(c => c.UseSqlServer(connectionString));
Hamed Nikzad answered 2019-10-09T17:38:04Z
translate from https://stackoverflow.com:/questions/45782446/unable-to-create-migrations-after-upgrading-to-asp-net-core-2-0