7

Sto tentando di rinominare le tabelle Identity 2.0 tramite lo strumento Migrazioni in EF6/Gestore pacchetti. Tuttavia, sta facendo esplodere una parte del modo attraverso. Sto semplicemente chiamando il seguente pezzo di codice dopo la "ApplicationDBContext Create" in IdentityModels.cs:Ridenominazione delle tabelle di identità con EF6 Migrazioni non riuscite

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 

      modelBuilder.Entity<IdentityUser>().ToTable("Users"); 
      modelBuilder.Entity<IdentityRole>().ToTable("Roles"); 
      modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); 
      modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); 
      modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); 
     } 

E poi soffia questo errore:

PM> Update-Database -Verbose 
Using StartUp project 'ProjectSender'. 
Using NuGet project 'ProjectSender'. 
Specify the '-Verbose' flag to view the SQL statements being applied to the target database. 
Target database is: 'Projectsender' (DataSource: x.x.x.x, Provider: System.Data.SqlClient, Origin: Configuration). 
Applying explicit migrations: [201505080059533_RenameTables]. 
Applying explicit migration: 201505080059533_RenameTables. 
EXECUTE sp_rename @objname = N'dbo.AspNetRoles', @newname = N'Roles', @objtype = N'OBJECT' 
IF object_id('[PK_dbo.AspNetRoles]') IS NOT NULL BEGIN 
    EXECUTE sp_rename @objname = N'[PK_dbo.AspNetRoles]', @newname = N'PK_dbo.Roles', @objtype = N'OBJECT' 
END 
Caution: Changing any part of an object name could break scripts and stored procedures. 
Caution: Changing any part of an object name could break scripts and stored procedures. 
EXECUTE sp_rename @objname = N'dbo.AspNetUserRoles', @newname = N'UserRoles', @objtype = N'OBJECT' 
IF object_id('[PK_dbo.AspNetUserRoles]') IS NOT NULL BEGIN 
    EXECUTE sp_rename @objname = N'[PK_dbo.AspNetUserRoles]', @newname = N'PK_dbo.UserRoles', @objtype = N'OBJECT' 
END 
EXECUTE sp_rename @objname = N'dbo.AspNetUserClaims', @newname = N'UserClaims', @objtype = N'OBJECT' 
IF object_id('[PK_dbo.AspNetUserClaims]') IS NOT NULL BEGIN 
    EXECUTE sp_rename @objname = N'[PK_dbo.AspNetUserClaims]', @newname = N'PK_dbo.UserClaims', @objtype = N'OBJECT' 
END 
EXECUTE sp_rename @objname = N'dbo.AspNetUserLogins', @newname = N'UserLogins', @objtype = N'OBJECT' 
IF object_id('[PK_dbo.AspNetUserLogins]') IS NOT NULL BEGIN 
    EXECUTE sp_rename @objname = N'[PK_dbo.AspNetUserLogins]', @newname = N'PK_dbo.UserLogins', @objtype = N'OBJECT' 
END 
IF object_id(N'[dbo].[FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId]', N'F') IS NOT NULL 
    ALTER TABLE [dbo].[AspNetUserClaims] DROP CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_UserId] 
System.Data.SqlClient.SqlException (0x80131904): Cannot find the object "dbo.AspNetUserClaims" because it does not exist or you do not have permissions. 
    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, Boolean asyncWrite) 
    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.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext`1 c) 
    at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) 
    at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext) 
    at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery() 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteSql(MigrationStatement migrationStatement, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(MigrationStatement migrationStatement, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection, DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinTransaction(IEnumerable`1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsWithinNewTransaction(IEnumerable`1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection) 
    at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClass30.<ExecuteStatements>b__2e() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements, DbTransaction existingTransaction) 
    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, VersionedModel targetModel, IEnumerable`1 operations, IEnumerable`1 systemOperations, Boolean downgrading, Boolean auto) 
    at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    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.UpdateInternal(String targetMigration) 
    at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b() 
    at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 
    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.Run() 
    at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 
    at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force) 
    at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0() 
    at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command) 
ClientConnectionId:c43cef2f-1614-40cc-a405-ecec90028871 
Error Number:4902,State:1,Class:16 
Cannot find the object "dbo.AspNetUserClaims" because it does not exist or you do not have permissions. 

E 'una remota di SQL Server 2014 Express. Tuttavia, ho temporaneamente reso il mio utente VS/sql un SysAdmin per sapere che non si trattava di un problema di autorizzazioni .... e le tabelle sono tutte presenti, compreso l'FK che sembra saltare in aria.

Sono tentato di eseguire solo lo script SQL che ricevo da (sul server SQL reale):

Update-Database -Script 

E poi fare un:

Add-Migration InitialCreate –IgnoreChanges 

Ma, temo altri errori e ostacoli dovrò saltare. Ogni aiuto è molto apprezzato.

+1

Sembra che hai bisogno di abbandonare le relazioni FK prima di rinominare (poi ri-applicare utilizzando nuovi nomi di tabella). - anche se pensavo che sp_rename l'avesse fatto per te ... –

+0

Grazie, sì, sono lieto di far uscire lo strumento migrazioni EF da whack modificando manualmente l'SQL. Sto avendo una vera battaglia con questa cosa. Tuttavia, penso che stia creando i comandi SQL nell'ordine sbagliato. Quindi, la mia ipotesi migliore è che non veda quel vincolo nella tabella AspNetUserClaims, perché nel momento in cui tenta di eliminare il vincolo che la tabella è già stata rinominata in UserClaims. Pertanto, AspNetUserClaims "non esiste" ... il che significa che dovrò intervenire manualmente perché non vedo un modo per aggirarlo ...? – SumNone

+0

Hai affermato che stai utilizzando Migrazioni, potresti provare a modificare quella migrazione specifica (invece di utilizzare onModelCreating), quindi applicare Update-Database. –

risposta

5

OnModelCreating è il posto giusto per farlo, ma si desidera anche sfruttare le migrazioni per questo tipo di cose. Detto questo, assumendo aggiungiamo le modifiche nostri "ApplicationDbContext" (nomi utilizzando progetto di default) entro OnModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Entity<ApplicationUser>().ToTable("Users"); 
    modelBuilder.Entity<IdentityRole>().ToTable("Roles"); 
    modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); 
    modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); 
    modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); 
} 

Calling Add-Migration AspNetIdentity_RenameTables dovrebbe generare il nostro script di migrazione per noi (questo presuppone una migrazione esistente esiste per creare le tabelle di identità utilizzando la denominazione di default):

public partial class AspNetIdentity_RenameTables : DbMigration 
{ 
    public override void Up() 
    { 
     RenameTable(name: "dbo.AspNetRoles", newName: "Roles"); 
     RenameTable(name: "dbo.AspNetUserRoles", newName: "UserRoles"); 
     RenameTable(name: "dbo.AspNetUsers", newName: "Users"); 
     RenameTable(name: "dbo.AspNetUserClaims", newName: "UserClaims"); 
     RenameTable(name: "dbo.AspNetUserLogins", newName: "UserLogins"); 
    } 

    public override void Down() 
    { 
     RenameTable(name: "dbo.UserLogins", newName: "AspNetUserLogins"); 
     RenameTable(name: "dbo.UserClaims", newName: "AspNetUserClaims"); 
     RenameTable(name: "dbo.Users", newName: "AspNetUsers"); 
     RenameTable(name: "dbo.UserRoles", newName: "AspNetUserRoles"); 
     RenameTable(name: "dbo.Roles", newName: "AspNetRoles"); 
    } 
} 

Ora chiamando Update-Database si prende cura di tutto il resto. Ovviamente, se avevi configurato DbInitializer usando l'inizializzatore di migrazione, questo sarebbe fatto per te al primo caricamento).

ora, abbiamo i tavoli rinominati:

Database Screenshot

Un esempio (con commit storia) può essere trovato su GitHub: https://github.com/bchristie/AspNetIdentity-RenameTables


Per aggiungere un po 'di chiarezza:

OnModelCreating ha lo scopo e consente a EF di conoscere relazioni, chiavi, relazioni tra entità e tabella, ecc. La funzione Migrazioni di EF funziona in modo eccezionale nel compiere un ulteriore passo avanti e nella gestione degli stati intermedi del database, quindi mi piace sfruttarlo quando è possibile.

Dato che IdentityDbContext ha le proprie dichiarazioni all'interno, dobbiamo superare la sua configurazione aggiungendo uno OnModelCreating (ma solo dopo aver chiamato il metodo base). Ora abbiamo tutta la struttura esistente, ma con un nuovo nome.

È anche importante fare riferimento alle entità con le quali si sta lavorando. Quindi, dal momento che il progetto predefinito utilizza uno ApplicationUser, questo è quello che faremo riferimento in modelBuilder.Entity<>().

+0

Eccellente, scrivi, grazie! Quindi, sembra che non ho nemmeno bisogno del modelBuilder.Entity (). ToTable ("Users"); linea, che avrebbe evitato i metodi DropForeignKey. Ho intenzione di ricominciare da zero e vedere se non posso andare avanti un po 'meglio questa volta. Apprezzo molto l'aiuto e le informazioni. – SumNone

2

Se si leggono i commenti sopra, si tratta di una soluzione più che di una soluzione reale.

First (e non correlato all'errore sopra), parte del codice di rinominare mio tavolo AspNetUsers mancava e quindi, quindi era una linea necessaria dalla mia funzione onModelCreating:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 

      modelBuilder.Entity<IdentityUser>().ToTable("Users"); 
      modelBuilder.Entity<ApplicationUser>().ToTable("Users"); //this line needed!! 
      modelBuilder.Entity<IdentityRole>().ToTable("Roles"); 
      modelBuilder.Entity<IdentityUserRole>().ToTable("UserRoles"); 
      modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogins"); 
      modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaims"); 
     } 

Anche dopo la correzione che , il codice di migrazione necessario veniva generato con il codice SQL nell'ordine errato e ancora lanciava l'errore sopra, facendo riferimento ai nomi delle tabelle precedenti dopo che la tabella era già stata rinominata. Così, ho dovuto modificare il file di migrazione direttamente e spostare i DropForeignKey metodi per la parte superiore davanti RenameTable metodi:

public override void Up() 
     { 
      DropForeignKey("dbo.AspNetUserClaims", "UserId", "dbo.AspNetUsers"); 
      DropForeignKey("dbo.AspNetUserLogins", "UserId", "dbo.AspNetUsers"); 
      DropForeignKey("dbo.AspNetUserRoles", "UserId", "dbo.AspNetUsers"); 
      RenameTable(name: "dbo.AspNetRoles", newName: "Roles"); 
      RenameTable(name: "dbo.AspNetUserRoles", newName: "UserRoles"); 
      RenameTable(name: "dbo.AspNetUsers", newName: "Users"); 
      RenameTable(name: "dbo.AspNetUserClaims", newName: "UserClaims"); 
      RenameTable(name: "dbo.AspNetUserLogins", newName: "UserLogins"); 
      DropIndex("dbo.UserRoles", new[] { "UserId" }); 
      DropIndex("dbo.UserClaims", new[] { "UserId" }); 
      DropIndex("dbo.UserLogins", new[] { "UserId" }); 
      AddColumn("dbo.UserRoles", "IdentityUser_Id", c => c.String(maxLength: 128)); 
      AddColumn("dbo.Users", "Discriminator", c => c.String(nullable: false, maxLength: 128)); 
      AddColumn("dbo.UserClaims", "IdentityUser_Id", c => c.String(maxLength: 128)); 
      AddColumn("dbo.UserLogins", "IdentityUser_Id", c => c.String(maxLength: 128)); 
      AlterColumn("dbo.UserClaims", "UserId", c => c.String()); 
      CreateIndex("dbo.UserRoles", "IdentityUser_Id"); 
      CreateIndex("dbo.UserClaims", "IdentityUser_Id"); 
      CreateIndex("dbo.UserLogins", "IdentityUser_Id"); 
      AddForeignKey("dbo.UserClaims", "IdentityUser_Id", "dbo.Users", "Id"); 
      AddForeignKey("dbo.UserLogins", "IdentityUser_Id", "dbo.Users", "Id"); 
      AddForeignKey("dbo.UserRoles", "IdentityUser_Id", "dbo.Users", "Id"); 
     } 

Al cambiamento che Update-Database eseguito correttamente.

Ho guardato un video tutorial di questo processo su www.asp.net/identity e ho letto diversi indizi su google e non so davvero perché il mio sia un errore e gli esempi non lo sono. Immagino di essere fortunato. Ma, qui è il mio ambiente, nel caso in cui si tratta di un bug:

  • MVC 5.2.3
  • EF 6.1.3
  • Identità 2.2.1
  • VS 2013
  • SQL Express 2014

On per il prossimo numero ... Ci vediamo presto ...

0

in primo luogo. Rinominare la classe ApplicationUser su ciò che si desidera, poiché è possibile rinominare con successo la tabella IdentityUser predefinita.

Poiché la classe ApplicationUser eredita da IdentityUser ed è ciò che l'applicazione fa effettivamente riferimento per i problemi del profilo utente. Pertanto, se non è stato modificato, il processo di modifica della tabella utilizzando la funzione onModelCreating() che riguarda il profilo utente darebbe errori di riferimento, di sicurezza o di relazione.

trovare lo screenshot allegato delle modifiche per comprendere meglio il mio punto. grazie vorrei che risolvesse il tuo problema

// Note this class is what i changed from ApplicationUser to just User 

public class User : IdentityUser 
    { 
     public async Task<ClaimsIdentity> 
      GenerateUserIdentityAsync(UserManager<User> manager) 
     { 
      .......... codes 
     } 
    } 


protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      base.OnModelCreating(modelBuilder); 


      base.OnModelCreating(modelBuilder); 

      // Rather than identityUser generic class , use the name of the renamed ApplicationUser being User 
      modelBuilder.Entity<User>().ToTable("User").Property(x => x.Id).HasColumnName("UserId"); 

      modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole"); 
      modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin"); 

      modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim").Property(x => x.Id).HasColumnName("ClaimId"); 
      modelBuilder.Entity<IdentityRole>().ToTable("Role").Property(x => x.Id).HasColumnName("RoleId"); 


     } 

trovare lo screenshot allegato delle modifiche per comprendere meglio il mio punto. grazie vorrei che risolvesse il tuo problema

Image of Default Aspnet Identity Tables Rename