Używamy Entity Framework 5.0 Code First i Automatic Migrations.Kod EF5 Pierwsze migracje: "Nazwy kolumn w każdej tabeli muszą być unikalne" błąd po użyciu RenameColumn
miałem klasy tak:
public class TraversalZones
{
public int Low { get; set; }
public int High { get; set; }
}
Wtedy zdaliśmy sobie sprawę, właściwości te nie były naprawdę odpowiednie nazwy, więc ich zmianie:
public class TraversalZones
{
public int Left { get; set; }
public int Top { get; set; }
}
Zmień nazwę refactored właściwie w całym projekcie , ale wiem, że automatyczne migracje nie są wystarczająco inteligentne, aby wykryć te jawne nazwy w IDE, więc najpierw sprawdziłem, czy jedyną oczekującą migracją była zmiana nazwy kolumny:
update-database -f -script
Na pewno po prostu pokazał, że SQL upuszcza niskie i wysokie wartości oraz dodaje lewy i górny. I dodaje ręczną migrację:
add-migration RenameColumns_TraversalZones_LowHigh_LeftTop
I stała się wygenerowany kod po prostu:
public override void Up()
{
RenameColumn("TraversalZones", "Low", "Left");
RenameColumn("TraversalZones", "High", "Top");
}
public override void Down()
{
RenameColumn("TraversalZones", "Left", "Low");
RenameColumn("TraversalZones", "Top", "High");
}
Potem zaktualizowała DB:
update-database -verbose
I got 2 Zmienia nazwę kolumny , tak jak się spodziewałem.
Kilka migracji później wykonałem kopię zapasową Produkcji i przywróciłem ją do lokalnego DB, aby przetestować kod na tym DB. Ta DB miał tabelę TraversalZones już utworzony w niej, ze starymi nazwami kolumn (niskie i wysokie) I oczywiście zaczął aktualizując go:
update-database -f -verbose
I Zmień nazwę komendy pojawił się na wyjściu - wszyscy pojawił dobrze:
EXECUTE sp_rename @objname = N'TraversalZones.Low', @newname = N'Left', @objtype = N'COLUMN'
EXECUTE sp_rename @objname = N'TraversalZones.High', @newname = N'Top', @objtype = N'COLUMN'
[Inserting migration history record]
Następnie uruchomiłem mój kod, który wykluczył, że baza danych zmieniła się od ostatniego uruchomienia, i że powinienem uruchomić update-database
....
Więc wpadłem go ponownie:
update-database -f -verbose
i jestem teraz zakleszczony na ten błąd:
No pending code-based migrations. Applying automatic migration:
201212191601545_AutomaticMigration.
ALTER TABLE [dbo].[TraversalZones] ADD [Left] [int] NOT NULL DEFAULT 0
System.Data.SqlClient.SqlException (0x80131904): Column names in each table must be unique. Column name 'Left' in table 'dbo.TraversalZones' is specified more than once.
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:c40408ee-def3-4553-a9fb-195366a05fff
Column names in each table must be unique. Column name 'Left' in table 'dbo.TraversalZones' is specified more than once.
więc wyraźnie Migracje jest zdezorientowany, czy kolumna „Lewy” wciąż musi dokonać do tego stołu; Zakładam, że RenameColumn pozostawiłoby rzeczy we właściwym stanie, ale wydaje się, że tak nie jest.
Kiedy zrzucić co to próbuje zrobić z update-database -f -script
, mam to staramy się robić dokładnie to, co by to zrobić jeśli instrukcja migracji nie były tam:
ALTER TABLE [dbo].[TraversalZones] ADD [Left] [int] NOT NULL DEFAULT 0
ALTER TABLE [dbo].[TraversalZones] ADD [Top] [int] NOT NULL DEFAULT 0
DECLARE @var0 nvarchar(128)
SELECT @var0 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.TraversalZones')
AND col_name(parent_object_id, parent_column_id) = 'Low';
IF @var0 IS NOT NULL
EXECUTE('ALTER TABLE [dbo].[TraversalZones] DROP CONSTRAINT ' + @var0)
ALTER TABLE [dbo].[TraversalZones] DROP COLUMN [Low]
DECLARE @var1 nvarchar(128)
SELECT @var1 = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'dbo.TraversalZones')
AND col_name(parent_object_id, parent_column_id) = 'High';
IF @var1 IS NOT NULL
EXECUTE('ALTER TABLE [dbo].[TraversalZones] DROP CONSTRAINT ' + @var1)
ALTER TABLE [dbo].[TraversalZones] DROP COLUMN [High]
INSERT INTO [__MigrationHistory] ([MigrationId], [Model], [ProductVersion]) VALUES ('201212191639471_AutomaticMigration', 0x1F8B08000...000, '5.0.0.net40')
Wydaje się to być błąd w Migracje.