43 votes

Migrations automatiques pour ASP.NET SimpleMembershipProvider

J'ai essayé d'utiliser les migrations automatiques avec mon nouveau projet MVC 4, mais cela ne fonctionne pas. I a suivi cet article de blog étape par étape.

J'ai ajouté les modifications à la UserProfile modèle de compte (le NotaryCode ) :

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public int NotaryCode { get; set; }
}

Puis j'ai écrit sur la console du gestionnaire de paquets enable-migrations et une classe Configuration est apparue (hérite de DbMigrationsConfiguration<Web.Models.UsersContext> ) alors je remplis la classe comme :

public Configuration()
{
    AutomaticMigrationsEnabled = true;
}

protected override void Seed(Atomic.Vesper.Cloud.Web.Models.UsersContext context)
{
    WebSecurity.InitializeDatabaseConnection(
            "DefaultConnection",
            "UserProfile",
            "UserId",
            "UserName", autoCreateTables: true);

    if (!Roles.RoleExists("Atomic"))
        Roles.CreateRole("Atomic");

    if (!Roles.RoleExists("Protocolista"))
        Roles.CreateRole("Protocolista");

    if (!Roles.RoleExists("Cliente"))
        Roles.CreateRole("Cliente");

    string adminUser = "randolf";

    if (!WebSecurity.UserExists(adminUser))
        WebSecurity.CreateUserAndAccount(
            adminUser,
            "12345",
            new { NotaryCode = -1 });

    if (!Roles.GetRolesForUser(adminUser).Contains("Atomic"))
        Roles.AddUsersToRoles(new[] { adminUser }, new[] { "Atomic" });
}

Et ensuite, j'ai essayé d'exécuter update-database -verbose mais ça ne marche pas. Je veux dire, c'est la sortie :

Il existe déjà un objet nommé 'UserProfile' dans la base de données.

PM> update-database -verbose
Using StartUp project 'Web'.
Using NuGet project 'Web'.
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Target database is: 'VesperCloud' (DataSource: .\SQLSERVER, Provider: System.Data.SqlClient, Origin: Configuration).
No pending code-based migrations.
Applying automatic migration: 201211051825098_AutomaticMigration.
CREATE TABLE [dbo].[UserProfile] (
    [UserId] [int] NOT NULL IDENTITY,
    [UserName] [nvarchar](max),
    [NotaryCode] [int] NOT NULL,
    CONSTRAINT [PK_dbo.UserProfile] PRIMARY KEY ([UserId])
)
System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'UserProfile' in the database.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement)
   at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
   at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, Boolean downgrading, Boolean auto)
   at System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.AutoMigrate(String migrationId, XDocument sourceModel, XDocument targetModel, Boolean downgrading)
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
   at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
ClientConnectionId:a7da0ddb-bccf-490f-bc1e-ecd2eb4eab04
**There is already an object named 'UserProfile' in the database.**

Je sais que l'objet existe. Je veux dire que j'essaie d'utiliser les migrations automatiques pour, précisément, modifier et exécuter sans recréer manuellement la base de données. Mais d'une manière ou d'une autre, cela ne fonctionne pas.

J'ai regardé la documentation MSDN et j'ai trouvé la propriété :

AutomaticMigrationDataLossAllowed = true;

Mais le mettre à vrai ne change rien. Je suppose qu'il me manque quelque chose mais je ne trouve pas quoi. Une idée ?

127voto

Haminh Nguyen Points 1496

update-database -verbose ne fonctionne pas car votre modèle a été modifié alors que votre table de données existait déjà.

Tout d'abord, assurez-vous que la classe UserProfile n'a pas été modifiée. Ensuite, exécutez :

Add-Migration InitialMigrations -IgnoreChanges

Cela devrait générer un fichier "InitialMigration" vierge. Maintenant, ajoutez toutes les modifications souhaitées à la classe UserProfile. Une fois les modifications ajoutées, exécutez à nouveau la commande de mise à jour :

update-database -verbose

Maintenant la migration automatique sera appliquée et la table sera modifiée avec vos changements.

6voto

lukew Points 531

Ce qui semble s'être passé ici, c'est que vous avez activé les migrations, puis exécuté l'application. En exécutant l'application avant d'utiliser la commande UpdateDatabase, EntityFramework aurait créé et rempli la base de données, mais comme la base de données n'existait pas lorsque vous avez activé les migrations, la migration InitialCreate n'a pas été créée. Les migrations pensent toujours que vous avez une base de données vide et veulent créer tous les objets de votre modèle.

Vous pouvez essayer de réactiver les migrations, ce qui générera une migration InitialCreate reflétant l'état actuel de la base de données. Dans ce cas, je sauvegarderais les modifications que vous avez apportées à la méthode d'amorçage et j'exécuterais "Enable-Migrations -Force", ce qui devrait recréer la migration et générer une migration IntialCreate. Vous pouvez alors repeupler votre méthode d'amorçage et exécuter la commande UpdateDatabase.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X