web-dev-qa-db-fra.com

Activer les migrations avec le contexte dans un assemblage séparé?

J'ai un projet sur lequel je veux exécuter mon update-database mais j'ai mes modèles et mon contexte dans un projet séparé.

Si j'exécute enable-migrations j'obtiens l'erreur suivante: Aucun type de contexte n'a été trouvé dans l'assembly 'MyProject'.

C'est probablement parce que mon contexte est dans MyProject.MVC.

Si je lance enable-migrations sur MyProject.MVC, je dois ajouter un fichier de configuration d'application. Je ne veux pas faire cela car je veux utiliser le code dans de nombreux projets.

Donc, puis-je exécuter enable-migrations contre MyProject et lui demander de rechercher le contexte dans MyProject.MVC?

61
Jon

Cela ne fonctionnera que dans EF 6, mais il y a eu un release qui a ajouté le paramètre -ContextProjectName à la commande -enable-migrations. En utilisant cette commande, vous pouvez effectuer les opérations suivantes:

enable-migrations -ContextProjectName MyProject.MVC -StartUpProjectName MyProject.MVC 
-ContextTypeName MyProject.MVC.MyContextFolder.MyContextName -ProjectName MyProject

Cela ajoutera des migrations à votre projet MyProject en utilisant le contexte du MyProject.MVC. Vous devez vous assurer que le projet avec les migrations contient une référence au projet avec votre contexte, c'est-à-dire, MyProject référence MyProject.MVC

98
SOfanatic

Vous ne pouvez exécuter "Enable-Migrations" que dans le projet contenant la classe de contexte de base de données.

Votre solution contiendra 2 projets:

1) MyProject.Models
    |- Migrations
        |- 201401061557314_InitialCreate.cs
        |- Configuration.cs
    |- MyContext.cs
    |- App.config (no connection string)


App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>


2) MyProject.MVC
        |- Filters
            |- InitializeSimpleMembershipAttribute.cs


InitializeSimpleMembershipAttribute.cs

namespace MyProject.MVC.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
    {
        private static SimpleMembershipInitializer _initializer;
        private static object _initializerLock = new object();
        private static bool _isInitialized;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Ensure ASP.NET Simple Membership is initialized only once per app start
            LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        }

        private class SimpleMembershipInitializer
        {
            public SimpleMembershipInitializer()
            {
                try
                {
                    Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, MyProject.Model.Migrations.Configuration>());

                    using (var context = new MyContext())
                    {
                        context.Database.Initialize(force: true);
                        if (!context.Database.Exists())
                        {
                            // Create the SimpleMembership database without Entity Framework migration schema
                            ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                        }
                    }

                    WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.Microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }
}

Définir MyProject.MVC en tant que projet de démarrage

Dans le gestionnaire de packages, sélectionnez le projet: MyProject.Models.

Puis exécutez "Enable-Migrations" pour créer le dossier "Migrations" dans MyProject.Models

Suivi de "Update-Database" -> les migrations utilisent la chaîne de connexion dans Web.config à partir du projet de démarrage pour effectuer la migration

12
cronixis

Voici une solution de contournement:

Ajoutez une classe dans MyProject (le projet pour les migrations). Faites que cette classe hérite du dbcontext (celui de MyProject.MVC).

Ensuite, exécutez les commandes de migration EF sur MyProject.

3
Jan Bizub

J'ai eu le même problème et j'utilise EntityFramework 4.3.1. Il semble que EF6 résolve ce problème (selon la réponse de @SOfanatic), mais je ne voulais pas passer à EF6 à cause de certaines modifications radicales (dans DataAnnotations, par exemple).

Donc, ce que j'ai fait pour résoudre ceci (et ce que j'ai appris au cours du processus):

  1. Créez une nouvelle solution (projet vide) et ajoutez le projet contenant le modèle pour lequel vous souhaitez activer les migrations (dans votre cas, MyProject.MVC). Vous devrez peut-être installer les packages NuGet requis avant de pouvoir ajouter le projet existant.

  2. Ajoutez un fichier de configuration avec une chaîne de connexion (ne vous inquiétez pas, cela n'a pour but que de tromper le moteur de migration). Copiez votre base de données existante dans le dossier de sortie du projet de modèle (vous devez utiliser MVC\bin\Debug). Assurez-vous que la chaîne de connexion dans le fichier de configuration pointe vers cette base de données:

    <connectionStrings>
        <add name="MyDB" providerName="System.Data.SqlServerCe.4.0" connectionString="DataSource=|DataDirectory|\MyDB.sdf"/>
      </connectionStrings>
    
  3. Puisque vous êtes dans une nouvelle solution, définissez votre projet de modèle en tant que projet de démarrage (vous pouvez supprimer le projet par défaut).

  4. Exécutez la commande enable-migrations dans la console du gestionnaire de packages. Il convient de créer un dossier Migrations avec deux fichiers: un fichier Configuration.cs et un fichier InitialCreate.cs horodaté. C'est bien d'avoir InitialCreate, c'est pourquoi vous avez mis votre base de données existante dans le dossier de sortie du projet de modèle (mais cela est facultatif).

  5. Rechargez votre solution d'origine afin que ces modifications soient mises à jour.

Ce que j'ai appris (d'après ce que j'ai compris):

  1. Le moteur de migration a besoin de quelque chose qui ressemble à une connexion valide pour fonctionner. Je créais ma chaîne de connexion en code (dans un autre projet) et cela ne fonctionnait pas. Je viens de donner au moteur Migrations une chaîne de connexion "valide" pour le faire fonctionner.
  2. Placez votre base de données où le moteur de migration peut la trouver (dossier de sortie du projet de modèle) afin qu'il crée un point de départ pour les migrations. Ce point de départ est essentiellement votre schéma de base de données écrit dans l'API de migration.
  3. Vous pouvez tout restaurer à votre état précédent une fois les migrations mises en place, et tout fonctionne correctement.
  4. Chaque fois que vous souhaitez ajouter manuellement une migration, vous devez à nouveau "tromper" le moteur de migration, comme pour la première fois. Je n'ai pas essayé les migrations automatiques, je suppose que cette approche fonctionne également.

En passant, j’utilise une base de données SQL Server CE 4.0, de sorte que certains aspects de la chaîne de connexion sont légèrement différents de ceux d’une base de données SQL Server standard ou d’une base de données locale. A part ça, tout est pareil.

J'espère que cela vous aidera et vous donnera un aperçu. Veuillez commenter si vous en savez plus sur le fonctionnement de ces migrations.

0
Hannish