J'ai donc essayé d'utiliser les migrations automatiques avec mon nouveau projet MVC 4, mais cela ne fonctionne pas. I suivi ce billet de blog étape par étape.
J'ai ajouté les modifications au modèle de compte UserProfile
(le champ 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; }
}
J'ai ensuite écrit sur la console du gestionnaire de paquets enable-migrations
et une classe de 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 puis j'ai essayé d'exécuter update-database -verbose
mais cela ne fonctionne pas. Je veux dire, c'est la sortie:
Il y a 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, j'essaie d'utiliser des 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.
Je regarde la documentation MSDN et trouve la propriété:
AutomaticMigrationDataLossAllowed = true;
Mais le définir sur true ne change rien. Je suppose que je manque quelque chose mais ne trouve pas quoi. Une idée?
update-database -verbose
ne fonctionne pas car votre modèle a été modifié après que votre table de données existait déjà.
Tout d'abord, assurez-vous qu'il n'y a pas de modification de la classe UserProfile. Ensuite, exécutez:
Add-Migration InitialMigrations -IgnoreChanges
Cela devrait générer un fichier "InitialMigration" vierge. Maintenant, ajoutez 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 le tableau sera modifié avec vos modifications.
Ce qui se passe 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 puisque lorsque vous avez activé les migrations, la base de données n'existait pas, elle n'a pas créé la migration InitialCreate. 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 qui reflète l'état actuel de la base de données. Dans ce cas, je voudrais enregistrer les modifications que vous avez apportées à la méthode de départ que d'exécuter "Enable-Migrations -Force", cela devrait recréer la migration et générer une migration IntialCreate. Vous pouvez ensuite repeupler votre méthode de départ et exécuter la commande UpdateDatabase.
J'avais les mêmes et triés de manière différente. Je suis allé sur ma base de données locale supprimé les tables UserProfile et autres tables ayant des contraintes de clé étrangère webpages_Membership, webpages_OAuthMembership, webpages_Roles, webpages_UsersInRoles tables. Tous ces éléments seront recréés lorsque vous exécuterez update-database -verbose.