web-dev-qa-db-fra.com

Ajouter une migration avec un assemblage différent

Je fais un projet dans ASP.NET CORE 1.0.0 et j'utilise EntityFrameworkCore. J'ai des assemblages séparés et ma structure de projet ressemble à ceci:

ProjectSolution
   -src
      -1 Domain
         -Project.Data
      -2 Api
         -Project.Api

Dans mon Project.Api est la classe Startup

public void ConfigureServices(IServiceCollection services)
    {            
        services.AddDbContext<ProjectDbContext>();

        services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ProjectDbContext>()
                .AddDefaultTokenProviders();
    }

La DbContext est dans mon projet Project.Data

public class ProjectDbContext : IdentityDbContext<IdentityUser>
{
    public ProjectDbContext(DbContextOptions<ProjectDbContext> options) : base(options)
    {

    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {

        var builder = new ConfigurationBuilder();
        builder.SetBasePath(Directory.GetCurrentDirectory());
        builder.AddJsonFile("appsettings.json");
        IConfiguration Configuration = builder.Build();

        optionsBuilder.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection"));
        base.OnConfiguring(optionsBuilder);
    }
}

Lorsque j'essaie de faire la migration initiale, j'obtiens cette erreur:

"Votre projet cible 'Project.Api' ne correspond pas à votre migration Assemblage 'Project.Data'. Changez votre projet cible ou votre assemblée de migration . Changez votre assemblée de migration en utilisant DbContextOptionsBuilder. Par exemple, options.UseSqlServer (connection , b => b.MigrationsAssembly ("Project.Api")). Par défaut, l’Assembly de migration est l’Assembly contenant le DbContext . Changez votre projet cible en projet de migration à l’aide du projet Default de la Console de gestion de packages. bas, ou en exécutant "dotnet ef" à partir du répertoire contenant le projet de migration. "

Après avoir vu cette erreur, j'ai essayé d'exécuter cette commande située dans Project.Api

dotnet ef --startup-project ../Project.Api --Assembly "../../1 Data/Project.Data" migrations add Initial

et j'ai eu cette erreur: 

"Valeur inattendue '../../1 Domaine/Projet.Données' pour l'option 'Assemblage'" 

Je dont know why I get this error, when I try to execute the command with the- Assembly` paramètre.

Je ne peux pas créer de migration initiale à partir d'un autre assemblage et j'ai recherché des informations à ce sujet, mais je n'ai obtenu aucun résultat.

Quelqu'un a-t-il eu des problèmes similaires?

13
kdar

Toutes les commandes EF ont cette vérification :

if (targetAssembly != migrationsAssembly) 
       throw MigrationsAssemblyMismatchError;

targetAssembly = le projet cible sur lequel vous opérez. Sur la ligne de commande, c'est le projet dans le répertoire de travail en cours. Dans Package Manager Console, il s'agit du projet sélectionné dans la liste déroulante située dans le coin supérieur droit de cette fenêtre.

migrationsAssembly = Assembly contenant le code pour les migrations. Ceci est configurable. Par défaut, il s'agira de l'assembly contenant le DbContext, dans votre cas, Project.Data.dll . Comme le message d'erreur le suggère, vous avez le choix entre deux options

1 - Changer d'assemblage cible.

cd Project.Data/
dotnet ef --startup-project ../Project.Api/ migrations add Initial

// code doesn't use .MigrationsAssembly...just rely on the default
options.UseSqlServer(connection)

2 - Modifier les migrations de l'Assemblée.

cd Project.Api/
dotnet ef migrations add Initial

// change the default migrations Assembly
options.UseSqlServer(connection, b => b.MigrationsAssembly("Project.Api"))
27
natemcmaster

J'avais le même problème jusqu'à ce que je remarque que sur la barre de menus de la console du gestionnaire de paquets, la barre supérieure>> "Projets par défaut" était supposée être "Project.Data" et non "Project.API".

Une fois que vous ciblez le "Project.Data" de la liste déroulante et lancez la migration, tout devrait bien se passer.

12
Dre Ross

J'ai couru sur le même problème et trouvé this

Nous essayons d’effectuer vos migrations sur une bibliothèque de classes? Moi aussi. Il s’avère que ce n’est pas encore supporté, nous devrons donc nous en occuper.

EDIT: j'ai trouvé la solution sur this git repo

4
Alan Jagar

Actuellement, je pense qu'EF ne prend en charge que l'ajout de migrations sur des projets pas encore sur des bibliothèques de classes.

Et juste note secondaire pour quiconque souhaite ajouter des migrations à un dossier spécifique de votre projet:

EF CLI supporte pas encore. J'ai essayé --data-dir mais cela n'a pas fonctionné.

La seule chose qui fonctionne est d'utiliser Package Manager Console:

  1. Choisissez votre projet par défaut
  2. le paramètre de commande use -OutputDir, par exemple, la commande Add-Migration InitConfigurationStore -OutputDir PersistedStores/ConfigurationStore, exportera le mgiration dans le dossier 'PersistedStores/ConfigurationStore' de mon projet. 

Mises à jour au 10/12/2017

public void ConfigureServices(IServiceCollection services)
{
    ...

    string dbConnectionString = services.GetConnectionString("YOUR_PROJECT_CONNECTION");
    string assemblyName = typeof(ProjectDbContext).Namespace;

    services.AddDbContext<ProjectDbContext>(options =>
        options.UseSqlServer(dbConnectionString,
            optionsBuilder =>
                optionsBuilder.MigrationsAssembly(assemblyName)
        )
   );

   ...
}
4
David Liang

Avec EF Core 2, vous pouvez facilement séparer votre projet Web de votre projet Data (DbContext). En fait, il vous suffit d'implémenter l'interface IDesignTimeDbContextFactory. Selon Microsoft docs , IDesignTimeDbContextFactory est:

Une fabrique pour la création d'instances DbContext dérivées. Implémentez ceci interface pour activer les services au moment du design pour les types de contexte qui n'en ont pas avoir un constructeur public par défaut. Au moment du design, dérivé DbContext des instances peuvent être créées pour permettre un temps de conception spécifique des expériences telles que les migrations. Les services au moment de la conception seront découvrir automatiquement les implémentations de cette interface qui se trouvent dans l'assemblée de démarrage ou la même assemblée que le contexte dérivé.

Dans l'extrait de code du bas, vous pouvez voir mon implémentation de DbContextFactory qui est définie dans mon projet Data:

public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
{
    public KuchidDbContext CreateDbContext(string[] args)
    {
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();

        var connectionString = configuration.GetConnectionString("Kuchid");

        dbContextBuilder.UseSqlServer(connectionString);

        return new KuchidDbContext(dbContextBuilder.Options);
    }
}

Maintenant, je peux initialiser la migration EF en définissant mon projet Web comme projet de démarrage et en sélectionnant mon projet Data dans la console du gestionnaire de packages.

Add-Migration initial

Vous pouvez trouver plus de détails ici . Cependant, cet article de blog utilise une classe obsolète au lieu de IDesignTimeDbContextFactory.

4
Ehsan Mirsaeedi

(ASP.NET Core 2+)

Avait le même problème. Voici ce que j'ai fait:

  1. Référencez le projet contenant le DbContext (Project.A) du projet qui contiendra les migrations (Project.B).

  2. Déplacez les migrations existantes de Project.A vers Project.B (si vous n'avez pas de migration, créez-les d'abord)

  3. Configurez les migrations Assembly dans Project.A

options.UseSqlServer (connectionString, x => x.MigrationsAssembly ("Project.A"));

En supposant que vos projets résident dans le même dossier parent:

  1. dotnet ef migrations add Init --project ../AskGoo.Data -c DbContext

Les migrations vont maintenant à Project.B

Source: Microsoft

3
Kaloyan Drenski
Add-Migration NewMigration -Project MyApp.Migrations
2
Majid joghataey

J'étais confronté à un problème similaire, bien que les réponses semblent assez simples, elles n'ont pas fonctionné ..__ Ma réponse est similaire à @Ehsan Mirsaeedi, avec un petit changement dans la classe DbContextFactory. Au lieu d'ajouter le nom de l'assembly de migration dans la classe de démarrage de l'API, j'ai mentionné dans la classe DbContextFactory qui fait partie du projet de données (bibliothèque de classes).

public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
{
   public KuchidDbContext CreateDbContext(string[] args)
   {
       var configuration = new ConfigurationBuilder()
          .SetBasePath(Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json")
          .Build();

       var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();

       var connectionString = configuration.GetConnectionString("connectionString");

       var migrationAssemblyName= configuration.GetConnectionString("migrationAssemblyName");

       dbContextBuilder.UseSqlServer(connectionString, o => o.MigrationAssembly(migrationAssemblyName));

       return new KuchidDbContext(dbContextBuilder.Options);
   }
}

Vous aurez besoin des extensions 'Microsoft.Extensions.Configuration' et 'Microsoft.Extensions.Configuration.Json' pour SetBasePath & AddJsonFile.

Note: Je pense que c'est juste un moyen de contourner le problème. Il devrait récupérer les options DbContextOptions de la classe de démarrage d’une manière ou d’une autre. Je suppose qu'il y a définitivement un problème de câblage. 

0
Mady

Pour tous ceux qui ont plusieurs projets de démarrage.

Notez que vous devez définir votre projet cible en tant que projet de démarrage - Project.Api (sous forme de question) devrait être le projet de démarrage.

J'espère que ça va aider quelqu'un :)

0
Atanas Sarafov