2015-02-20 14 views
7

Sto utilizzando Entity Framework con le migrazioni di prima del codice. Devo aumentare la lunghezza di una colonna VARCHAR(50) su VARCHAR(100) e aggiornare tutti i record in quella colonna raddoppiando la stringa. Quindi "abc" diventa "abcabc" (eccetto che i valori saranno più lunghi di tre caratteri).Utilizzare Entity Framework per aggiornare la lunghezza e i dati della colonna nella singola migrazione

Sarebbe bello poter eseguire questa operazione in un unico codice prima della migrazione, ma ho difficoltà a farlo funzionare. Ho provato ad utilizzare questo codice:

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(); 
} 

ma ho ottenuto questo errore:

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).

ho pensato Gee che è strano. Forse non posso usare Entity Framework all'interno di una prima migrazione di codice? Così ho provato questo codice:

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(); 
} 

ma ho ottenuto questo errore:

String or binary data would be truncated.

Poi, però, è la dichiarazione ALTER TABLE per rendere il campo più lungo non entrata in vigore prima che i UPDATE eseguita l'istruzione? Quindi ho modificato l'istruzione UDPDATE in una stringa di 50 caratteri e funzionava correttamente. L'esecuzione di Update-Database -Verbose indica inoltre che non è in esecuzione la dichiarazione ALTER TABLE prima dell'istruzione UPDATE.

Quindi qual è l'affare qui? Devo eseguire lo ALTER TABLE in una migrazione, quindi il codice per aggiornare la tabella in un altro?

risposta

13

Il punto è che EF esegue le migrazioni come parte di una transazione.

si apre una nuova transazione all'interno up, che non è necessario, è sufficiente utilizzare

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

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

In questo caso la funzione Sql() correrebbe nello stesso contesto di transazione e non dovrebbe apparire l'errore.

MODIFICA: chiarimento sul contesto di transazione della funzione Sql().

+0

Quindi quando si utilizza la funzione Sql viene eseguita nella propria transazione? Quando dici che non è necessario, cosa intendi? – d512

+0

no, volevo dire che l'istruzione alter table è in esecuzione all'interno di una transazione. Se si utilizza la funzione Sql(), viene eseguita nello stesso ambito della transazione. Se apri un nuovo SqlConnection, utilizzerà un contesto di transazione separato. Aggiornerò la risposta per chiarire questo. –

+0

Vedo, quindi è necessario eseguire entrambe le istruzioni all'interno della stessa transazione e ne stavo creando una nuova che non sapeva del fatto che l'altra aumentava le dimensioni del campo. Quindi è possibile ottenere la transazione che viene creata implicitamente per la migrazione e trasferirla nel contesto del database? Per ragioni che non ho rivelato nella mia domanda, sarebbe preferibile utilizzare la funzione Sql(). – d512

Problemi correlati