O mnieBlogGitHub

Migracja .NET Core 2.2 do 3.1

20 March, 2020 - 3 min read

W wersjach .NET Core można się nie łapać - co jakiś wychodzą nowe, nie zawsze wiadomo, czy i kiedy przenosić się na nowsze wersje oraz jakie będą tego skutki. (Osoby ze świata "starego" .NETa pamiętają, że to nigdy nie była prosta decyzja.) Z pomocą przychodzi jednak sam Microsoft, mówiąc wprost, jakie wersje wspiera, a jakie już skazuje na zapomnienie. Stan na dzisiaj:

Lista wersji .NET Core SDK wraz z datami zakończenia wsparcia

Gdy ze zdziwieniem spostrzegłem, że wersja 2.2, na której oparty był ostatni projekt, w którym pracowałem - nie jest już wspierana od Bożego Narodzenia 2019, zaordynowałem przenosiny na 3.1. To jest wersja rekomendowana i będzie wspierana przez najbliższe 2 lata. Jak dla mnie spoko.

No to myślę sobie, że zmieniam w csprojach tylko jedną linijkę:

 <TargetFramework>netcoreapp3.1</TargetFramework>

...i fajrant. 😎

To jednak nie jest takie proste. Poniżej przedstawiam listę kolejnych kroków, które trzeba zrobić.

  1. Podbij wersję w csprojach jak wyżej.
  2. Po skompilowaniu dostaniesz na pewno błędy z informacją o konieczności usunięcia referencji do niektórych nugetów lub podbcia wersji. Ja musiałem m.in.:
  3. usunąć referencję do Microsoft.AspNetCore.App z projektu WebAPI,
  4. podbić wersję Microsoft.Extensions.DependencyInjection do 3.1.x
  5. Zrób parę modyfikacji w Startup.cs (to jest przykład dla projektu WebAPI, bez żadnych widoków czy Razor pages):
  6. dodaj services.AddControllers(); na początku ConfigureServices,
  7. zmień CompatibilityVersion na Version_3_0 w services.AddMvc(...).SetCompatibilityVersion(...),
  8. zamień użycie IHostingEnvironment na IWebHostEnvironment w argumentach metod,
  9. w metodzie Configure:

    • dodaj app.UseRouting(); (raczej na początku),
    • dodaj app.UseAuthorization(); (o ile jest uwierzytelnianie w projekcie),
    • dodaj na końcu:
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});
  1. Potem podbij EF Core do 3.1 (oczywiście, jeśli jest używane w Twoim projekcie). Nie zapomnij też o podbiciu Microsoft.EntityFrameworkDesign, jeśli Twój kontekst jest w innym projekcie niż apka webowa.
  2. Jeśli masz testy Twoich repozytoriów (lub innego kodu czytającego coś bazy) - na pewno testy się wywalą. Chodzi tu o to, że w EF Core 3 została wprowadzona zasadnicza zmiana: w poprzedniej wersji EF Core tam, gdzie nie potrafił zbudować poprawnego, bardziej złożonego query - na chama wykonywał operację po stronie klienta (co skutkowało miejscami niespodziewanie niską wydajnością zapytań); w wersji 3 inżynierowie Microsoftu postanowili zrobić odwrotnie: tam, gdzie query byłoby w wersji 2 wykonane po stronie klienta, teraz framework rzuca wyjątek - i sugeruje, żeby zrobić tę kwerendę explicite po stronie klienta. Umownie można powiedzieć, że w tych miejscach trzeba dodać to przysłowiowe ToList, żeby najpierw dane ściągnąć do klienta.
  3. Jeśli sam utrzymujesz build maszynę, to czeka Cię jeszcze jedna niespodzianka - odpowiednie sparowanie wersji .NET Core SDK i EF Core CLI Tool. Tutaj też nastąpiła zmiana - otóż, dotychczas EF Core CLI Tool (czyli coś, co umożliwia pisanie dotnet ef ...) było częścią całego SDK. Teraz już tak nie jest i należy tego toola zainstalować oddzielnie. Żeby było jeszcze trudniej, wersja tego narzędzia musi być "sparowana" z wersją .NET Core SDK. U mnie zadziałał zestaw:
dev@build-machine:~$ dotnet --version
3.1.102
dev@build-machine:~$ dotnet-ef --version
Entity Framework Core .NET Core Command-line Tools
3.1.1

To ważne, bo na ten moment najnowszą wersję EF Core CLI Tools jest 3.1.2, które nijak nie chce współgrać z .NET Core 3.1.102. Tak więc EF Core CLI Tool musi być zainstalowany z podaniem konkretnej wersji, a nie domyślnie.

  1. Po drodze jeszcze podbiłem wersję xUnit, ale już nie pamiętam, czy to było konieczne. :) (Ale wówczas trzeba też podbić xunit.runner.visualstudio i - chyba? - Microsoft.NET.Test.Sdk - żeby można było odpalać unit testy w Resharperze.)
© 2020, Built with Gatsby