2015-02-20 10 views
7

Używam Entity Framework z pierwszymi migracjami kodu. Muszę zwiększyć długość kolumny VARCHAR(50) do VARCHAR(100) i zaktualizować wszystkie rekordy w tej kolumnie, podwajając ciąg znaków. Zatem "abc" zamienia się w "abcabc" (z wyjątkiem tego, że wartości będą dłuższe niż trzy znaki).Użyj Entity Framework do aktualizacji długości kolumny i danych w pojedynczej migracji

Byłoby miło móc to zrobić podczas pierwszej migracji pierwszego kodu, ale mam problem z jego uruchomieniem. Po raz pierwszy spróbował wykorzystać ten kod:

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

ale mam ten błąd:

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

myślałem Gee, że to dziwne. Może nie mogę użyć Entity Framework podczas pierwszej migracji kodu? Więc próbowałem ten kod:

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

ale mam ten błąd:

String or binary data would be truncated.

Potem chociaż jest oświadczenie ALTER TABLE aby boiska już nie ze skutkiem przed UPDATE tras stwierdzeniem? Zmieniłem więc instrukcję UDPDATE, aby była łańcuchem o długości 50 znaków i działało poprawnie. Uruchamianie Update-Database -Verbose wskazuje również, że nie jest uruchomione instrukcja ALTER TABLE przed instrukcją UPDATE.

Więc o co tu chodzi? Czy muszę uruchomić ALTER TABLE w jednej migracji, a następnie kod, aby zaktualizować tabelę w innej?

Odpowiedz

13

Chodzi o to, że EF wykonuje migracje w ramach transakcji.

otworzyć nową transakcję wewnątrz górę, co nie jest konieczne, wystarczy użyć

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

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

W tym przypadku funkcja Sql() zostanie uruchomiony w tym samym kontekście transakcji, a błąd nie powinien się pojawić.

EDYCJA: wyjaśnienie kontekstu transakcji funkcji Sql().

+0

Więc kiedy używasz funkcji Sql działa w swojej własnej transakcji? Kiedy mówisz, że to nie jest konieczne, co masz na myśli? – d512

+0

Nie, chodzi mi o to, że instrukcja tabeli zmian działa w ramach transakcji. Jeśli używasz funkcji Sql(), jest ona wykonywana w tym samym zakresie transakcji. Jeśli otworzysz nowy SqlConnection, użyje oddzielnego kontekstu transakcji. Zaktualizuję odpowiedź, aby to wyjaśnić. –

+0

Rozumiem, więc musisz uruchomić obie instrukcje w ramach tej samej transakcji, a ja tworzyłem nową, która nie wiedziała o tym, że druga zwiększyła rozmiar pola. Czy możliwe jest pobranie transakcji, która jest niejawnie utworzona dla migracji i przekazanie jej do kontekstu bazy danych? Z powodów, których nie ujawniłem w moim pytaniu, lepiej byłoby skorzystać z funkcji Sql(). – d512