2015-02-20 3 views
7

Ich verwende Entity Framework mit Code-Erstmigrationen. Ich muss die Länge einer VARCHAR(50) Spalte zu VARCHAR(100) erhöhen und alle Datensätze in dieser Spalte aktualisieren, indem Sie die Zeichenfolge verdoppeln. So wird "abc" zu "abcabc" (außer dass die Werte länger als drei Zeichen sind).Verwenden Sie Entity Framework zum Aktualisieren der Spaltenlänge und der Daten bei einer einzelnen Migration.

Es wäre schön, dies in einem einzigen Code erste Migration zu tun, aber ich habe Probleme, es funktioniert. Ich versuchte zunächst, mit diesem Code:

AlterColumn("dbo.SomeTable", "SomeField", c => c.String(maxLength: 100, unicode: false)); 

using (TheEntityContext ctx = new TheEntityContext()) 
{ 
    foreach (Entities.SomeTable st in ctx.SomeTables) 
     st.SomeField = st.SomeField + st.SomeField; 

    ctx.SaveChanges(); 
} 

aber ich habe diesen Fehler:

The model backing the 'TheEntityContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

Ich dachte, gee, das ist seltsam. Vielleicht kann ich Entity Framework nicht innerhalb einer ersten Code-Migration verwenden? Also habe ich versucht, diesen Code:

AlterColumn("dbo.SomeTable", "SomeField", c => c.String(maxLength: 100, unicode: false)); 

using (SqlConnection conn = new SqlConnection(connStr)) 
{ 
    conn.Open(); 
    string sql = "UPDATE SomeTable SET SomeField = SomeField + '' + SomeField"; 
    SqlCommand cmd = new SqlCommand(sql, conn); 
    cmd.ExecuteNonQuery(); 
} 

aber ich habe diesen Fehler:

String or binary data would be truncated.

Dann wenn ich die ALTER TABLE Anweisung, das Feld zu machen länger nicht wirksam vor den Läufen UPDATE Aussage zu nehmen? So änderte ich die UDPDATE Anweisung, um eine Zeichenfolge mit 50 Zeichen zu sein, und es lief gut. Das Ausführen von Update-Database -Verbose zeigt außerdem an, dass es die ALTER TABLE-Anweisung vor der UPDATE-Anweisung nicht ausführt.

Also, was ist der Deal hier? Muss ich die ALTER TABLE in einer Migration dann den Code ausführen, um die Tabelle in einem anderen zu aktualisieren?

Antwort

13

Der Punkt ist, dass EF Migrationen als Teil einer Transaktion ausführt.

Sie öffnen eine neue Transaktion innerhalb up, die einfach nicht notwendig ist, in diesem Fall

AlterColumn("dbo.SomeTable", "SomeField", c => c.String(maxLength: 100, unicode: false)); 

Sql("UPDATE dbo.SomeTable SET SomeField = '' + SomeField + SomeField"); 

verwenden die Sql() Funktion in der gleichen Transaktionskontext und der Fehler sollte nicht auftreten laufen würde.

BEARBEITEN: Erläuterung zum Transaktionskontext von Sql() Funktion.

+0

Also, wenn Sie die Sql-Funktion verwenden läuft in einer eigenen Transaktion? Wenn du sagst, dass es nicht notwendig ist, was meinst du? – d512

+0

nein, was ich meinte war, dass die alter table-Anweisung innerhalb einer Transaktion läuft. Wenn Sie die Funktion Sql() verwenden, wird sie im selben Transaktionsbereich ausgeführt. Wenn Sie eine neue SqlConnection öffnen, wird ein separater Transaktionskontext verwendet. Ich werde die Antwort aktualisieren, um dies zu klären. –

+0

Ich sehe, also müssen Sie beide Anweisungen innerhalb der gleichen Transaktion ausführen, und ich habe eine neue erstellt, die nicht über die Tatsache wusste, dass der andere die Feldgröße erhöhte. Ist es also möglich, die implizit für die Migration erstellte Transaktion in den Datenbankkontext zu überführen? Aus Gründen, die ich in meiner Frage nicht angegeben habe, wäre die Verwendung der Funktion Sql() vorzuziehen. – d512

Verwandte Themen