Невозможно создать миграции после обновления до ASP.NET Core 2.0


109

После обновления до ASP.NET Core 2.0 я больше не могу создавать миграции.

я собираюсь

«Произошла ошибка при вызове метода BuildWebHost в классе Program. Продолжение без поставщика службы приложений. Ошибка: произошла одна или несколько ошибок. (Невозможно открыть базу данных« ... », запрошенную именем входа. Ошибка входа в систему. Вход не удалось для пользователя '...' "

и

«Невозможно создать объект типа 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();
}

3
Возможно проблема не в Program.cs. Вероятно, это использование инструкции для загрузки исходных данных в конце вашего метода Configure: DbInitializer.Initialize (context); Если у вас есть эта инструкция, прокомментируйте ее: //DbInitializer.Initialize(context); Затем выполните инструкции по миграции для проверки. Если возникает проблема, обращайтесь к классу DbInitializer.cs.
Miguel Torres C

1
Находится ли ваш класс MyContext в другом проекте библиотеки классов?
Орхун

Такая же проблема здесь, контекст находится в другой библиотеке. Если id добавляет в контекст констуктор без параметра, миграции работают, но с той же ошибкой: (Произошла ошибка при вызове метода BuildWebHost в классе Program. Продолжение без поставщика службы приложения. Ошибка: ссылка на объект не установлена к экземпляру объекта.)
iBoonZ

Вы разрешили это в конце концов?
Конрад Вильтерстен 08

@MiguelTorresC благодарит за этот комментарий. Я закомментировал свои методы посева, и миграции снова начали работать. Благодаря тонну !!!
Амит Филипс

Ответы:


123

Вы можете добавить класс, реализующий 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.

ресурс


2
Я получаю: файл конфигурации appsettings.json не найден и не является обязательным. Физический путь - C: \ Users \ XXX \ Documents \ Visual Studio 2017 \ Projects \ XXX \ src \ XXX.Api \ bin \ Debug \ netcoreapp2.0 \ appsettings.json. Мои настройки приложения находятся в C: \ Users \ XXX \ Documents \ Visual Studio 2017 \ Projects \ XXX \ src \ XXX.Api.
Рефтинской

Убедитесь, что у вас есть файл appsettings.json, настроенный на локальное копирование, это должно решить проблему, из-за которой он не найден
DaImTo

1
Это решение вводит зависимость от Entity Framework в ваше хост-приложение (в моем случае это веб-проект). Есть ли способ обойти это? Я хотел бы, чтобы моя библиотека репозитория содержала файлы EF, а не вводила EF в веб-приложение.
Banoona

Несмотря на то, что это принятый ответ, этот лучше: stackoverflow.com/a/52671330/1737395 Действительно, выполнение миграции с флагом --verbose очень помогает
barbara.post

73

Нет необходимости в IDesignTimeDbContextFactory.

Бегать

add-migration initial -verbose

это раскроет детали под

Произошла ошибка при доступе к 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'.

3
Да -Verbose помогает раскрыть настоящую проблему. В моем случае в автозагрузку не добавлены службы AddDbContext.
sudhakarssd

3
dotnet ef migrations добавляет InitialCreate --verbose
barbara.post

4
@tchelidze Спасибо за это, в моем случае у меня не было конструктора без параметров в моем ApplicationDbContext.
Тьяго Авила

1
Это фантастический совет, должен быть принятый ответ
Аврохом Исроэль

1
Большое спасибо, это помогло мне найти мою проблему и решить ее. В моем случае это был «Конструктор без параметров, определенный для типа 'Data.Access.DAL.MainDbContext'.», И поэтому я просто удалил параметры из конструктора, и он работал как по волшебству!
Сара

25

Решение 1. (Найдите проблему в 99% случаев)

Установить проект веб-приложения как запускаемый проект

Выполните следующие команды с -verboseопцией.

Add-Migration Init -Verbose

-verbose опция помогает реально раскрыть реальную проблему, содержит подробные ошибки.

Решение 2:

Переименуйте BuildWebHost()в CreateWebHostBuilder(), потому что Entity Framework Core toolsожидайте найти CreateHostBuilderметод, который настраивает хост без запуска приложения.

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

.NET Core 3.1

Переименовать BuildWebHost()вCreateHostBuilder()

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Решение 3:

Убедитесь, что вы добавили Dbcontextк внедрению зависимостей: AddDbContext<TContext>и ваш тип DbContext TContext, и соответствующий ему будут DbContextOptions<TContext>доступны для внедрения из контейнера службы. Это требует добавления аргумента конструктора к вашему DbContextтипу, который принимает DbContextOptions<TContext>.

Пример: в Startup.cs

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

Код AppDbContext :

public class AppDbContext: DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
      :base(options)
    { }

}

1
Это сработало для меня. Изменена функция BuildWebHost в Program.cs от public static IWebHostBuilder BuildWebHost(string[] args)к public static IWebHost BuildWebHost(string[] args)с .Build()теперь включены в функции
zola25

1
Ребята, если вы используете ASP.NET Core 2.1+, ваш метод BuildWebHost будет иметь другое имя - CreateWebHostBuilder из-за docs.microsoft.com/en-us/aspnet/core/migration/ ... поэтому переименуйте CreateWebHostBuilder в BuildWebHost и миграция найдет BuildWebHost и возьмите от него DbContext.
KEMBL

2
Спасибо, приятель, решено после того, как потратил 2 часа на настройку без использованияIDesignTimeDbContextFactory
Азри Закария

3
Спасибо за флаг "-Verbose". Это помогло мне найти основную причину исключения.
Sergey_T 04

21
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(), потому что при миграции по умолчанию используется этот метод.


4
КАКИЕ. Это следует рекламировать на каждой странице, посвященной этой проблеме , если вы серьезно . Мгновенный успех. Спасибо.
Хаим Илия

Спаси мой день !!! Это очень странная ошибка. Я использую .net core 3.0 с предварительным просмотром 7, и эта ошибка все еще существует
Д. Тодоров,

@DTodorov прочитал этот devblogs.microsoft.com/dotnet/…
sherox

D Todorov Просто переименуйте BuildWebHost () в CreateHostBuilder ()
Али Баят

1
@WernerCD Cuz Worker использует метод CreateHostBuilder (), который реализует IHostBuilder of Net Core 3
sherox

11

В моем случае причиной проблемы было несколько запускаемых проектов. В моем решении есть три проекта: Mvc, Api и Dal. DbContext и миграции в проекте Dal.

Я настроил несколько запускаемых проектов. Когда я нажал кнопку «Пуск», были запущены проекты Mvc и Api. Но в этом случае я получал эту ошибку.

«Невозможно создать объект типа MyContext. Добавьте реализацию IDesignTimeDbContextFactory в проект или см. Https://go.microsoft.com/fwlink/?linkid=851728 для дополнительных шаблонов, поддерживаемых во время разработки».

Я смог успешно добавить миграцию после установки Mvc в качестве единственного запускаемого проекта и выбора Dal в консоли диспетчера пакетов.


1
Спасибо, со мной случилось то же самое. Мне пришлось сменить запускаемый проект на место, где существуют классы Startup / Program. Сообщение об ошибке - плохая шутка.
Любош Чурго

1
Выходные сообщения действительно разочаровывали. Неожиданно для меня не был выбран стартап-проект. По этой причине не удалось создать dbContext. Спасибо.
upkit

1
Спасибо, сэр ... Я сэкономил много времени
Навид Хан

7

В 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 в классе Program ... Ошибка входа. Ошибка входа для пользователя '...' "

Но это не ошибка, потому что миграция будет создана, и ее можно будет выполнить. Так что просто проигнорируйте эту ошибку в первый раз, и, поскольку Db будет существовать, больше не повторится.


4

пожалуйста, убедитесь, что у вас есть ссылка

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

5
Я использую то, <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />что включает эту ссылку. Я попытался также включить вышеупомянутое, но без изменений.
ruhm

4

Вы можете попробовать это решение из этого обсуждения , которое было вдохновлено этим сообщением .

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

2
Я все еще получаю: Добавить реализацию «IDesignTimeDbContextFactory <DatabaseContext>» ......
Рефтинской

4

Мне действительно помогла эта статья: https://elanderson.net/2017/09/unable-to-create-an-object-of-type-applicationdbcontext-add-an-implementation-of-idesigntimedbcontextfactory/

Основная идея состоит в том, что при переходе с .net core 1 на 2 все инициализации db должны быть перенесены из StartUp.cs в Program.cs. В противном случае задачи EF пытаются запустить вашу базу данных при выполнении задач.

«В официальных документах по миграции ( https://docs.microsoft.com/en-us/ef/core/miscellaneous/1x-2x-upgrade ) есть хороший раздел под названием« Переместить код инициализации базы данных », который, похоже, у меня есть пропущено. Поэтому, прежде чем вы отправитесь в кроличьи норы, как я, убедитесь, что это не то, что вызывает у вас необходимость добавить реализацию IdesignTimeDbContextFactory. "


Спасибо, мне это тоже помогло.
Сергей

3

Из

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, вы можете изменить свой класс Program в соответствии с новым шаблоном.

Добавить Factory в .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);
        }
    }

3

У меня была эта проблема, и она была решена с помощью Set -> Web Application (Included Program.cs) Project to -> Set as Startup Project »

Затем запустите -> add-migration initial -verbose

в консоли диспетчера пакетов

Установить как запускаемый проект


Спасибо, единственное решение, которое сработало для меня, - это установить веб-проект как запускаемый, и это именно то, что нужно было сделать.
user3012760

3

Если вы хотите избежать этой вещи IDesignTimeDbContextFactory: просто убедитесь, что вы не используете какой-либо метод Seed в своем запуске. Я использовал статический метод начального значения в своем запуске, и это вызывало у меня эту ошибку.


2

Ранее вы настраивали исходные данные в методе Configure в Startup.cs. Теперь рекомендуется использовать метод Configure только для настройки конвейера запросов. Код запуска приложения принадлежит методу Main.

Реорганизованный метод Main. Добавьте следующие ссылки в Program.cs:

using Microsoft.Extensions.DependencyInjection;

using MyProject.MyDbContextFolder;

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



2

В моем случае , я получил эту проблему , потому что у меня был метод , называемый SeedData.EnsurePopulated () вызываются на моем Startup.cs файл.

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

РЕШЕНИЕ

Перед выполнением миграции просто закомментируйте вызов класса SeedData в файле Startup.cs .

// SeedData.EnsurePopulated(app);

Это решило мою проблему, и надеюсь, что ваша проблема также решена таким же образом.


1

Я столкнулся с той же проблемой. У меня в решении два проекта. который

  1. API
  2. Сервисы и репо, содержащие контекстные модели

Изначально проект API был задан как Startup project.

Я изменил проект Startup на тот, который содержит классы контекста. если вы используете Visual Studio, вы можете установить проект как запускаемый:

откройте проводник решений >> щелкните правой кнопкой мыши контекстный проект >> выберите "Установить как запускаемый проект"


1

Прежде всего убедитесь, что вы настроили свою базу данных в Startup.cs моем случае, я получал эту ошибку, так как я не указал ниже вStartup.cs

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection"), x => x.MigrationsAssembly("<Your Project Assembly name where DBContext class resides>")));

1

Использование ASP.NET Core 3.1 и EntityFrameWorkCore 3.1.0. Переопределение OnConfiguring класса контекста только с помощью конструктора без параметров

```protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
               .SetBasePath(Directory.GetCurrentDirectory())
               .AddJsonFile("appsettings.json")
               .Build();
            var connectionString = configuration.GetConnectionString("LibraryConnection");
            optionsBuilder.UseSqlServer(connectionString);
        }
    }
```

1

Я столкнулся с ошибкой

«Невозможно создать объект типа MyContext. Добавьте реализацию IDesignTimeDbContextFactory в проект или см. Https://go.microsoft.com/fwlink/?linkid=851728 для дополнительных шаблонов, поддерживаемых во время разработки».

Так решилась моя проблема. Выполните приведенную ниже команду, находясь в каталоге решения.

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

Здесь Application - мой стартовый проект, содержащий класс Startup.cs, а Infrastructure - мой проект, содержащий класс DbContext.

затем запустите обновление, используя ту же структуру.

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

0

У меня такая же проблема, так как я имел в виду старую - Microsoft.EntityFrameworkCore.Tools.DotNet

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

После обновления до более новой версии проблема решилась.


0

В файле appsettings.json основного проекта я установил «Копировать в выходной каталог» на «Копировать всегда», и это сработало.


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

Хотя это может ответить на вопрос авторов, в нем отсутствуют некоторые поясняющие слова и ссылки на документацию. Фрагменты исходного кода не очень полезны без некоторых фраз. Вы также можете найти очень полезным, как написать хороший ответ . Пожалуйста, отредактируйте свой ответ.
hellow

0

Вы также можете использовать в конструкторе класса запуска, чтобы добавить файл json (в котором находится строка подключения) в конфигурацию. Пример:

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

        _config = builder.Build();
    }

0

Для меня это было потому, что я изменил Output Typeсвой стартап-проект с Console Applicationна Class Library.

Возврат к Console Applicationсработал.


0

У меня была эта проблема в решении, в котором есть:

  • проект .NET Core 2.2 MVC
  • проект .NET Core 3.0 Blazor
  • Контекст БД в проекте библиотеки классов .NET Standard 2.0

Я получаю сообщение «невозможно создать объект ...», когда проект Blazor установлен как запускаемый, но не, если проект MVC установлен как запускаемый проект.

Это меня озадачивает, потому что в консоли диспетчера пакетов (где я создаю миграцию) у меня есть проект по умолчанию, установленный на библиотеку классов C #, которая фактически содержит контекст БД, и я также указываю контекст БД в мой призыв добавить-миграцию add-migration MigrationName -context ContextName, поэтому кажется странным, что Visual Studio заботится о том, какой запускаемый проект сейчас установлен.

Я предполагаю, что причина в том, что когда проект Blazor является запускаемым проектом, PMC определяет версию .NET как Core 3.0 из запускаемого проекта, а затем пытается использовать это для запуска миграции в классе .NET Standard 2.0. библиотека и столкновение с каким-то конфликтом.

Независимо от причины, изменение запускаемого проекта на проект MVC, ориентированный на Core 2.2, а не на проект Blazor, устранило проблему.


0

Для меня проблема заключалась в том, что я запускал команды миграции не в том проекте. Выполнение команд внутри проекта, содержащего Startup.cs, а не проекта, содержащего DbContext, позволило мне обойти эту конкретную проблему.


0

В моем случае помогает установка проекта StartUp в init. Вы можете сделать это, выполнив

dotnet ef migrations add init -s ../StartUpProjectName

-4

У меня была такая же проблема. Просто изменил ap.jason на application.jason, и проблема устранилась.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.