1

Ich verwende zuerst EF-Code. Ich muss den Datentyp des Primärschlüssels einer Tabelle in unserer Produktionsdatenbank ändern.Ändern des Datentyps des Primärschlüssels in Produktions-DB

public class Course 
{ 
    [Key] 
    public Guid Id {get; set;} //This needs to be changed to int 

    public string Name {get;set;} 

    public virtual ICollection<Group> Groups {get;set;} 
} 

public class Group 
{ 
    [Key] 
    public Guid Id {get; set;} 

    public string Name {get;set;} 

    public virtual ICollection<Course> Courses{get;set;} 
} 

Als oben ist eine Viele-Viele-Beziehung hat EF erstellt eine Tabelle beitreten GroupCourses automatisch mit PK FK & sowohl als Group_Id und Course_Id. Was bis jetzt gut ist.

Jetzt muss ich den Primärschlüssel in Course Einheit zu int von Guid ändern.

Ich habe den Datentyp von Guid zu int geändert und erfolgreich eine neue Migration erstellt. Aber wenn ich versuche, den Befehl update-database auszuführen, erhalte ich einen Fehler.

Operand Typ Zusammenstoß: unique ist unvereinbar mit int in Abfrage

Ich bin nicht sicher, wie der obigen Fehler zu beheben.

Auch ich denke, es ist unmöglich, den Datentyp eines Primärschlüsselfeldes zu ändern, ohne Daten zu verlieren (natürlich können wir manuell aus dem Backup kopieren). Ich hoffe, ich liege falsch.

Kann mir bitte jemand sagen, gibt es einen besseren Weg, dies zu erreichen, ohne Daten zu verlieren?

HINWEIS: Ich habe durch andere SO-Beiträge und andere Internet-Foren gegangen, aber kein Glück.

+0

Können Sie eine Migration durchführen, um einen CourseTemp hinzuzufügen, der alle Daten aus Ihrer alten Course-Tabelle mit der 'Seed()' Methode in den Temp hochlädt? Dann könnten Sie eine andere Migration durchführen, um den Original-Kurs zu löschen und die CoureseTemp-Klasse/-Tabelle umzubenennen? – Bwolfing

Antwort

1

Sie erhalten die Art Zusammenstoß Fehler, da die erzeugte Migration direkt ALTER COLUMN auf den betroffenen Spalten zu tun versucht, den Typ Guid-integer zu ändern, und es ist nicht möglich, da die Guid Werte nicht implizit auf integer Werte umgewandelt werden.

Sie müssen Ihre Migration manuell ändern. Entfernen Sie die AlterColumn Zeilen. Um Ihre bestehenden Kurs-IDs ohne Datenverlust zu migrieren, können Sie die vorhandenen Guid Spalten vorübergehend umbenennen (Suffix _Old hinzufügen), neue Spalten mit dem richtigen neuen Namen und Typ erstellen, den Inhalt der Beziehungstabelle mit den richtigen Werten füllen UPDATE mit einem SELECT und löschen schließlich die alten Spalten:

public override void Up() 
{ 
    DropForeignKey("dbo.GroupCourses", "Course_Id", "dbo.Courses"); 
    DropIndex("dbo.GroupCourses", new[] { "Course_Id" }); 
    DropPrimaryKey("dbo.Courses"); 
    DropPrimaryKey("dbo.GroupCourses"); 

    //Removed: AlterColumn("dbo.Courses", "Id", c => c.Int(nullable: false, identity: true)); 
    RenameColumn("dbo.Courses", "Id", "Id_Old"); //Added 
    AddColumn("dbo.Courses", "Id", c => c.Int(nullable: false, identity: true)); //Added 

    //Removed: AlterColumn("dbo.GroupCourses", "Course_Id", c => c.Int(nullable: false)); 
    RenameColumn("dbo.GroupCourses", "Course_Id", "Course_Id_Old"); //Added 
    AddColumn("dbo.GroupCourses", "Course_Id", c => c.Int(nullable: false)); //Added 
    Sql(@"UPDATE gc SET gc.Course_Id = c.Id " 
      + "FROM dbo.GroupCourses as gc " 
      + "INNER JOIN dbo.Courses as c ON gc.Course_Id_Old = c.id_Old"); //Added 

    DropColumn("dbo.GroupCourses", "Course_Id_Old"); //Added 
    DropColumn("dbo.Courses", "Id_Old"); //Added 

    AddPrimaryKey("dbo.Courses", "Id"); 
    AddPrimaryKey("dbo.GroupCourses", new[] { "Group_Id", "Course_Id" }); 
    CreateIndex("dbo.GroupCourses", "Course_Id"); 
    AddForeignKey("dbo.GroupCourses", "Course_Id", "dbo.Courses", "Id", cascadeDelete: true); 
} 

ich im Code markiert die Linien I mit den Kommentaren //Added und //Removed geändert. Der Rest des Codes ist der Originalcode der Migration, der mit Add-Migration generiert wurde, nachdem der Eigenschaftstyp im Modell in int geändert wurde.

Sie müssen nur die Werte in der Spalte in der Beziehungstabelle mit UPDATE füllen. Die Werte in der Spalte Courses.Id werden automatisch generiert, da es sich um eine identity Spalte handelt.

Sie sollten auch herausfinden, die Down() Methode und implementieren Sie den umgekehrten Prozess, oder lassen Sie es so, wie es ist, wenn Sie wirklich nie Downgrade der Datenbank auf eine vorherige Migration.

Sie können dies auch tun, indem Sie den Code zwischen der Migration und dem Seeder aufteilen. Es wäre konzeptionell korrekter, da Sie die Migrationen für Schemaänderungen und den Seeder für Datenänderungen verwenden sollten. Aber ich denke, dass es einfacher ist, und Sie brauchen nur eine Migration, während Sie mit dem Seeder-Ansatz zwei Migrationen benötigen: eine mit dem gesamten obigen Code mit Ausnahme der UPDATE und die Sätze, die die _Old Spalten fallen lassen, und eine andere einfach mit dem Fallenlassen der _Old Spalten. Der UPDATE Teil wäre in der Sämaschine implementiert.

Eine Warnung: Der SQL-Code im UPDATE-Satz funktioniert mit Sql Server, funktioniert aber möglicherweise nicht mit anderen Datenbank-Engines. Es ist ein weiterer Nachteil der Verwendung der Migration anstelle der Sämaschine.

+0

Sehr detaillierte Antwort. Danke :-) – Venky

+0

Gern geschehen! – Diana

Verwandte Themen