web-dev-qa-db-fra.com

Impossible de créer des migrations après la mise à niveau vers ASP.NET Core 2.0

Après la mise à niveau vers ASP.NET Core 2.0, il semble que je ne puisse plus créer de migrations.

Je suis en train 

"Une erreur s'est produite lors de l'appel de la méthode 'BuildWebHost' sur la classe 'Programme'. Poursuite sans le fournisseur de services de l'application. Erreur: Une ou plusieurs erreurs se sont produites. (Impossible d'ouvrir la base de données" ... "à la demande de .__ La connexion a échoué. La connexion a échoué pour l'utilisateur '...' "

et

"Impossible de créer un objet de type 'MyContext'. Ajoutez une implémentation De 'IDesignTimeDbContextFactory' au projet ou consultez https://go.Microsoft.com/fwlink/?linkid=851728 pour les modèles supplémentaires pris en charge au moment de la conception. "

La commande que j'avais précédemment exécutée était $ dotnet ef migrations add InitialCreate --startup-project "..\Web" (à partir du projet/dossier avec le DBContext).

Chaîne de connexion: "Server=(localdb)\\mssqllocaldb;Database=database;Trusted_Connection=True;MultipleActiveResultSets=true"

Ceci est mon 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();
}
49
ruhm

Vous pouvez ajouter une classe qui implémente IDesignTimeDbContextFactory dans votre projet Web.

Voici l exemple de code:

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

Ensuite, accédez à votre projet de base de données et exécutez la commande suivante depuis la ligne de commande:

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.

Ressource

65
jaaso

Pas besoin de IDesignTimeDbContextFactory.

Courir 

add-migration initial -verbose 

cela révélera les détails sous 

Une erreur s'est produite lors de l'accès à IWebHost dans la classe 'Programme'. Continuer sans le fournisseur de services d'application. 

warning, qui est la racine cause du problème.

Dans mon cas, le problème était d'avoir ApplicationRole : IdentityRole<int> et d'appeler services.AddIdentity<ApplicationUser, IdentityRole>(), ce qui causait l'erreur ci-dessous.

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'.
16
tchelidze

Dans le fichier AppContext.cs, à côté de la classe AppContext, ajoutez une autre classe:

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

Cela résoudra votre deuxième problème:

"Impossible de créer un objet de type 'MyContext'. Ajoutez une implémentation de 'IDesignTimeDbContextFactory' au projet,

Après cela, vous pourrez ajouter-migration Initial et l'exécuter en exécutant update-database command . Toutefois, si vous exécutez ces commandes alors qu'il n'existe pas encore de base de données dans votre serveur SQL Server local, vous obtiendrez l'avertissement comme votre première erreur: "Une erreur

s'est produite lors de l'appel de la méthode 'BuildWebHost' sur la classe 'Programme' ... Le échec de la connexion. Échec de la connexion pour l'utilisateur '...' "

Mais ce n’est pas une erreur, car la migration sera créée et pourra être exécutée . Ignorez donc cette erreur pour la première fois, et cette dernière, puisque Db existera, ne se reproduira plus.

4
borisdj

Dans mon cas, le problème était dû à plusieurs projets de démarrage. J'ai trois projets dans ma solution: MVC, Api et Dal. DbContext et Migrations dans le projet Dal.

J'avais configuré plusieurs projets de démarrage. Les projets Mvc et Api étaient en cours d'exécution lorsque j'ai cliqué sur Démarrer. Mais dans ce cas, j'ai eu cette erreur.

"Impossible de créer un objet de type 'MyContext'. Ajoutez une implémentation De 'IDesignTimeDbContextFactory' au projet ou consultez https://go.Microsoft.com/fwlink/?linkid=851728 pour les modèles supplémentaires pris en charge au moment de la conception. "

Je pourrais réussir à ajouter la migration après avoir défini Mvc comme seul projet de démarrage et sélectionné Dal dans la console du gestionnaire de packages.

3

Vous pouvez essayer cette solution depuis cette discussion , qui a été inspirée par cet article

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

Cet article m'a vraiment beaucoup aidé: https://elanderson.net/2017/09/unable-to-create-an-object-of-type-applicationdbcontext-add-an-implementation-of-idesigntimedbcontextfactory/

L'idée de base est que, lors du passage de .net core 1 à 2, toute l'initialisation de la base de données doit être déplacée de StartUp.cs vers Program.cs. Sinon, les tâches EF essaient et exécutent les inits de votre base de données lorsqu’ils effectuent des tâches.

"Il existe une section Nice dans les documents de migration officiels ( https://docs.Microsoft.com/en-us/ef/core/misc Miscellaneous/1x-2x-upgrade ) intitulée" Déplacer le code d'initialisation de la base de données "qui Donc, avant de vous attaquer aux trous de lapin, assurez-vous que ce n’est pas ce qui vous oblige à ajouter une implémentation de IdesignTimeDbContextFactory. "

3
Rtype

veuillez vérifier que vous avez la référence

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

Dans mon cas, j'ai eu le problème parce que j'avais une méthode appelée SeedData.EnsurePopulated () qui était appelée sur mon fichier 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);
    }
}

Le travail de SeedData class consiste à ajouter des données initiales à la table de la base de données. Son code est:

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

SOLUTION

Avant de procéder à la migration, commentez simplement l’appel de SeedData class dans le fichier Startup.cs.

// SeedData.EnsurePopulated(app);

Cela a résolu mon problème et espère que votre problème sera également résolu de la même manière.

2
yogihosting

Auparavant, vous configuriez les données de départ dans la méthode Configure de Startup.cs. Il est maintenant recommandé d'utiliser la méthode Configure uniquement pour configurer le pipeline de demandes. Le code de démarrage de l'application appartient à la méthode Main.

La méthode principale refactorisée. Ajoutez les références suivantes au 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
Miguel Torres C

Si vous souhaitez éviter ces problèmes IDesignTimeDbContextFactory: Assurez-vous simplement que vous n'utilisez aucune méthode Seed dans votre démarrage. J'utilisais une méthode de départ statique dans mon démarrage et cela causait cette erreur pour moi.

2
codeYouLaterBro

Il y a un problème avec ef seeding db de Startup.Configure in 2.0 ... vous pouvez toujours le faire avec ce travail. Testé et a bien fonctionné

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

2
Nick G.

Une meilleure solution:

Si votre projet de démarrage est une application ASP.NET Core, les outils tentent d'obtenir l'objet DbContext auprès du fournisseur de services de l'application.

L'outil tente d'abord d'obtenir le fournisseur de services en appelant Program.BuildWebHost() et en accédant à la propriété IWebHost.Services.

ajoutez cette méthode après Main, dans Program.cs

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

De

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

Lorsque vous créez une nouvelle application ASP.NET Core 2.0, ce raccord est inclus par défaut. Dans les versions précédentes de EF Core et ASP.NET Core, les outils essaient d'appeler directement Startup.ConfigureServices afin de obtenir le fournisseur de services de l'application, mais ce modèle n'est plus fonctionne correctement dans les applications ASP.NET Core 2.0. Si vous mettez à niveau une application ASP.NET Core 1.x à 2.0, vous pouvez modifier votre programme classe à suivre le nouveau modèle.

Ajouter une usine dans .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);
        }
    }
2
Anton Swanevelder

J'ai eu ce problème et cela a résolu par Set -> Projet d'application Web (inclus Program.cs) à -> "Set as Startup Project"

Puis exécutez -> add-migration initial -verbose 

dans la console du gestionnaire de packages

Définir comme projet de démarrage

1
Ali Ahmadi

J'ai rencontré le même problème. J'ai deux projets dans la solution. lequel

  1. API
  2. Services et repo, qui contiennent des modèles de contexte

Initialement, le projet API était défini en tant que projet de démarrage.

J'ai changé le Projet de démarrage en celui qui contient les classes de contexte. Si vous utilisez Visual Studio, vous pouvez définir un projet comme projet de démarrage en:

ouvrir la solution Explorer >> cliquez avec le bouton droit sur le projet de contexte >> sélectionnez Définir comme projet de démarrage

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

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

Il suffit de renommer BuildWebHost en CreateWebHostBuilder, car la migration utilise cette méthode par défaut.

0
sherox

Vous pouvez également utiliser dans le constructeur de la classe de démarrage pour ajouter un fichier json (où se trouve la chaîne de connexion) à la configuration. Exemple:

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

        _config = builder.Build();
    }
0
Vio

J'ai eu le même problème depuis que je faisais référence vieux- Microsoft.EntityFrameworkCore.Tools.DotNet

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

Après la mise à niveau vers la nouvelle version, le problème a été résolu

0
vinayak hegde

Tout d’abord, assurez-vous que vous avez configuré votre base de données dans Startup.cs. Dans mon cas, j’obtenais cette erreur car je n’ai pas précisé ce qui suit dans Startup.cs.

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

J'ai eu ce problème dans une solution qui a:

  • un projet .NET Core 2.2 MVC
  • un projet .NET Core 3.0 Blazor
  • Contexte de base de données dans un projet de bibliothèque de classes .NET Standard 2.0

Je reçois le message "Impossible de créer un objet ..." lorsque le projet Blazor est défini comme projet de démarrage, mais pas si le projet MVC est défini comme projet de démarrage.

Cela me laisse perplexe, car dans la console du gestionnaire de package (où je crée la migration), le projet Par défaut est défini sur une bibliothèque de classe C # qui contient en réalité le contexte de base de données, et je spécifie également le contexte de base de données dans mon appel à add-migration add-migration MigrationName -context ContextName, il semble donc étrange que Visual Studio se soucie du projet de démarrage actuellement défini.

J'imagine que la raison en est que, lorsque le projet Blazor est le projet de démarrage, le PMC détermine la version de .NET comme étant Core 3.0 à partir du projet de démarrage, puis tente de l'utiliser pour exécuter les migrations sur la classe .NET Standard 2.0. bibliothèque et frapper un conflit de quelque sorte.

Quelle que soit la cause, le remplacement du projet de démarrage par le projet MVC qui cible Core 2.2 plutôt que le projet Blazor a résolu le problème.

0
tomRedox

J'ai eu le même problème. Il suffit de remplacer ap.jason par application.jason et de corriger le problème.

0
AliAzra

Pour moi, c’est parce que j’ai changé le Output Type de mon projet de démarrage de Console Application à Class Library.

Retourner à Console Application a fait l'affaire.

0
Robouste

Dans le fichier appsettings.json du projet principal, j'avais défini "Copier dans le répertoire de sortie" sur "Copier toujours" et cela a fonctionné.

0
geet

Exemple de classe de contexte DB pour les applications de console centrale .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);
        }
    }
}
0
Isanka Thalagala