Zmiany powodujące niezgodność w programie EF Core 9 (EF9)

Ta strona dokumentuje zmiany interfejsu API i zachowania, które mogą przerwać istniejące aplikacje aktualizowane z programu EF Core 8 do EF Core 9. Pamiętaj, aby przejrzeć wcześniejsze zmiany powodujące niezgodność w przypadku aktualizacji z wcześniejszej wersji programu EF Core:

Struktura docelowa

Program EF Core 9 jest przeznaczony dla platformy .NET 8. Oznacza to, że istniejące aplikacje przeznaczone dla platformy .NET 8 mogą nadal to robić. Aplikacje przeznaczone dla starszych wersji platform .NET, .NET Core i .NET Framework będą musiały być przeznaczone dla platformy .NET 8 lub .NET 9, aby korzystać z platformy EF Core 9.

Podsumowanie

Uwaga

Jeśli używasz usługi Azure Cosmos DB, zapoznaj się z oddzielną sekcją poniżej dotyczącą zmian powodujących niezgodność usługi Cosmos DB.

Zmiana powodująca niezgodność Wpływ
EF.Functions.Unhex() teraz zwraca byte[]? Niski
Sprawdzono poprawność argumentów wartości null argumentów sqlFunctionExpression Niski

Zmiany o niskim wpływie

EF.Functions.Unhex() teraz zwraca byte[]?

Problem ze śledzeniem nr 33864

Stare zachowanie

Funkcja EF.Functions.Unhex() została wcześniej oznaczona adnotacją, aby zwrócić element byte[].

Nowe zachowanie

Począwszy od programu EF Core 9.0, funkcja Unhex() jest teraz oznaczona adnotacją, aby zwrócić wartość byte[]?.

Dlaczego

Unhex() jest tłumaczony na funkcję SQLite unhex , która zwraca wartość NULL dla nieprawidłowych danych wejściowych. W związku Unhex() z tym zwrócona null w tych przypadkach niezgodna z adnotacją.

Środki zaradcze

Jeśli masz pewność, że zawartość tekstowa przekazana do Unhex() reprezentuje prawidłowy ciąg szesnastkowy, możesz po prostu dodać operator forgiving o wartości null jako potwierdzenie, że wywołanie nigdy nie zwróci wartości null:

var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();

W przeciwnym razie dodaj sprawdzanie wartości null dla wartości null dla wartości Unhex().

Sprawdzono poprawność argumentów wartości null argumentów sqlFunctionExpression

Problem ze śledzeniem nr 33852

Stare zachowanie

Wcześniej można było utworzyć element SqlFunctionExpression z inną liczbą argumentów i argumentów propagacji wartości null.

Nowe zachowanie

Począwszy od programu EF Core 9.0, program EF zgłasza teraz, jeśli liczba argumentów i argumentów propagacji wartości null nie jest zgodna.

Dlaczego

Brak pasującej liczby argumentów i argumentów propagacji wartości null może prowadzić do nieoczekiwanego zachowania.

Środki zaradcze

Upewnij się, że element argumentsPropagateNullability ma taką samą liczbę elementów jak .arguments W razie wątpliwości użyj false argumentu dopuszczalności null.

Zmiany powodujące niezgodność w usłudze Cosmos

Rozbudowane prace nad ulepszaniem dostawcy usługi Cosmos DB w wersji 9.0. Zmiany obejmują szereg zmian powodujących niezgodność; Jeśli uaktualniasz istniejącą aplikację, przeczytaj uważnie poniższe informacje.

Zmiana powodująca niezgodność Wpływ
Właściwość dyskryminująca jest teraz nazwana $type zamiast Discriminator Wys.
Właściwość id nie zawiera już dyskryminujących domyślnie Wys.
Synchronizacja we/wy za pośrednictwem dostawcy usługi Azure Cosmos DB nie jest już obsługiwana Śred.
Zapytania SQL muszą teraz bezpośrednio projektować wartości JSON Śred.
Niezdefiniowane wyniki są teraz automatycznie filtrowane z wyników zapytania Śred.
Niepoprawnie przetłumaczone zapytania nie są już tłumaczone Śred.
HasIndex teraz zgłasza zamiast ignorowania Niski
IncludeRootDiscriminatorInJsonId zmieniono nazwę na HasRootDiscriminatorInJsonId 9.0.0-rc.2 Niski

Zmiany o dużym wpływie

Właściwość dyskryminująca jest teraz nazwana $type zamiast Discriminator

Problem ze śledzeniem nr 34269

Stare zachowanie

Program EF automatycznie dodaje właściwość dyskryminującą do dokumentów JSON w celu zidentyfikowania typu jednostki reprezentowanej przez dokument. W poprzednich wersjach programu EF ta właściwość JSON była domyślnie nazwana Discriminator .

Nowe zachowanie

Począwszy od programu EF Core 9.0, właściwość dyskryminująca jest teraz domyślnie wywoływana $type . Jeśli masz istniejące dokumenty w usłudze Cosmos DB z poprzednich wersji programu EF, używają one starego Discriminator nazewnictwa, a po uaktualnieniu do programu EF 9.0 zapytania dotyczące tych dokumentów nie powiedzą się.

Dlaczego

Nowa praktyka JSON używa $type właściwości w scenariuszach, w których należy zidentyfikować typ dokumentu. Na przykład. Plik System.Text.Json platformy NET obsługuje również polimorfizm przy użyciu $type jako domyślnej nazwy właściwości dyskryminującej (docs). Aby dostosować się do reszty ekosystemu i ułatwić współdziałanie z narzędziami zewnętrznymi, wartość domyślna została zmieniona.

Środki zaradcze

Najprostszym ograniczeniem jest po prostu skonfigurowanie nazwy właściwości dyskryminującej na Discriminatorwartość , tak jak poprzednio:

modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");

Wykonanie tej czynności dla wszystkich typów jednostek najwyższego poziomu sprawi, że program EF będzie zachowywał się tak jak wcześniej.

W tym momencie, jeśli chcesz, możesz również zaktualizować wszystkie dokumenty, aby użyć nowego $type nazewnictwa.

Właściwość id zawiera teraz tylko właściwość klucza EF domyślnie

Problem ze śledzeniem nr 34179

Stare zachowanie

Wcześniej program EF wstawił dyskryminującą wartość typu jednostki do id właściwości dokumentu. Jeśli na przykład zapisano Blog typ jednostki z właściwością zawierającą Id 8, właściwość JSON id będzie zawierać Blog|8wartość .

Nowe zachowanie

Począwszy od programu EF Core 9.0, właściwość JSON id nie zawiera już wartości dyskryminującej i zawiera tylko avlue właściwości klucza. W powyższym przykładzie właściwość JSON id będzie po prostu .8 Jeśli masz istniejące dokumenty w usłudze Cosmos DB z poprzednich wersji programu EF, mają one wartość dyskryminującą we właściwości JSON id , a po uaktualnieniu do programu EF 9.0 zapytania względem tych dokumentów nie powiedzą się.

Dlaczego

Ponieważ właściwość JSON id musi być unikatowa, dyskryminator został wcześniej dodany do niej, aby umożliwić istnienie różnych jednostek o tej samej wartości klucza, na przykład w Blog przypadku właściwości i Post z właściwością Id zawierającą 8 w tym samym kontenerze i partycji. Zakładano, że jest to oczekiwane przez deweloperów używanych do relacyjnych baz danych, gdzie każdy typ jednostki jest mapowany na własną tabelę i dlatego ma własną przestrzeń kluczy.

Program EF 9.0 ogólnie zmienił mapowanie tak, aby był bardziej zgodny z typowymi praktykami i oczekiwaniami usługi Cosmos DB, zamiast odpowiadać oczekiwaniom użytkowników pochodzących z relacyjnych baz danych. Ponadto posiadanie wartości dyskryminującej we id właściwości utrudniało zewnętrznym narzędziom i systemom interakcję z dokumentami JSON generowanymi przez program EF. Takie systemy zewnętrzne nie są ogólnie świadome wartości dyskryminacyjnych ef, które są domyślnie uzyskiwane z typów platformy .NET.

Środki zaradcze

Najprostszym ograniczeniem jest po prostu skonfigurowanie programu EF w celu uwzględnienia dyskryminującego we właściwości JSON id , tak jak poprzednio. W tym celu wprowadzono nową opcję konfiguracji:

modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();

Wykonanie tej czynności dla wszystkich typów jednostek najwyższego poziomu sprawi, że program EF będzie zachowywał się tak jak wcześniej.

Jeśli chcesz, możesz również zaktualizować wszystkie dokumenty, aby przepisać ich właściwość JSON id . Należy pamiętać, że jest to możliwe tylko wtedy, gdy jednostki różnych typów nie współużytkują tej samej wartości identyfikatora w tym samym kontenerze.

Zmiany o średnim wpływie

Synchronizacja we/wy za pośrednictwem dostawcy usługi Azure Cosmos DB nie jest już obsługiwana

Problem ze śledzeniem nr 32563

Stare zachowanie

Wcześniej wywoływanie metod synchronicznych, takich jak ToList lub SaveChanges spowodowałoby zablokowanie synchronicznego używania .GetAwaiter().GetResult() programu EF Core podczas wykonywania wywołań asynchronicznych względem zestawu SDK usługi Azure Cosmos DB. Może to spowodować zakleszczenie.

Nowe zachowanie

Począwszy od programu EF Core 9.0, program EF jest teraz domyślnie zgłaszany podczas próby użycia synchronicznych operacji we/wy. Komunikat o wyjątku to "Usługa Azure Cosmos DB nie obsługuje synchronicznych operacji we/wy. Pamiętaj, aby używać metod asynchronicznych i prawidłowo oczekiwać tylko podczas korzystania z platformy Entity Framework Core w celu uzyskania dostępu do usługi Azure Cosmos DB. Zobacz https://aka.ms/ef-cosmos-nosync , aby uzyskać więcej informacji.

Dlaczego

Synchroniczne blokowanie metod asynchronicznych może spowodować zakleszczenie, a zestaw SDK usługi Azure Cosmos DB obsługuje tylko metody asynchroniczne.

Środki zaradcze

W programie EF Core 9.0 błąd można pominąć za pomocą:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}

Oznacza to, że aplikacje powinny przestać używać interfejsów API synchronizacji z usługą Azure Cosmos DB, ponieważ nie jest to obsługiwane przez zestaw SDK usługi Azure Cosmos DB. Możliwość pomijania wyjątku zostanie usunięta w przyszłej wersji programu EF Core, po której jedyną opcją będzie użycie asynchronicznych interfejsów API.

Zapytania SQL muszą teraz bezpośrednio projektować wartości JSON

Problem ze śledzeniem nr 25527

Stare zachowanie

Wcześniej program EF wygenerował zapytania, takie jak następujące:

SELECT c["City"] FROM root c

Takie zapytania powodują, że usługa Cosmos DB opakowuje każdy wynik w obiekcie JSON w następujący sposób:

[
    {
        "City": "Berlin"
    },
    {
        "City": "México D.F."
    }
]
Nowe zachowanie

Począwszy od programu EF Core 9.0, program EF dodaje teraz VALUE modyfikator do zapytań w następujący sposób:

SELECT VALUE c["City"] FROM root c

Takie zapytania powodują, że usługa Cosmos DB zwraca wartości bezpośrednio, bez otoki:

[
    "Berlin",
    "México D.F."
]

Jeśli aplikacja korzysta z zapytań SQL, takie zapytania są prawdopodobnie uszkodzone po uaktualnieniu do programu EF 9.0, ponieważ nie zawierają VALUE modyfikatora.

Dlaczego

Zawijanie każdego wyniku w dodatkowym obiekcie JSON może spowodować obniżenie wydajności w niektórych scenariuszach, przeładowanie ładunku wyniku JSON i nie jest naturalnym sposobem pracy z usługą Cosmos DB.

Środki zaradcze

Aby rozwiązać ten problem, wystarczy dodać VALUE modyfikator do projekcji zapytań SQL, jak pokazano powyżej.

Niezdefiniowane wyniki są teraz automatycznie filtrowane z wyników zapytania

Problem ze śledzeniem nr 25527

Stare zachowanie

Wcześniej program EF wygenerował zapytania, takie jak następujące:

SELECT c["City"] FROM root c

Takie zapytania powodują, że usługa Cosmos DB opakowuje każdy wynik w obiekcie JSON w następujący sposób:

[
    {
        "City": "Berlin"
    },
    {
        "City": "México D.F."
    }
]

Jeśli którykolwiek z wyników był niezdefiniowany (np. City właściwość była nieobecna w dokumencie), zwrócono pusty dokument, a program EF zwróci null ten wynik.

Nowe zachowanie

Począwszy od programu EF Core 9.0, program EF dodaje teraz VALUE modyfikator do zapytań w następujący sposób:

SELECT VALUE c["City"] FROM root c

Takie zapytania powodują, że usługa Cosmos DB zwraca wartości bezpośrednio, bez otoki:

[
    "Berlin",
    "México D.F."
]

Zachowanie usługi Cosmos DB polega na automatycznym filtrowaniu undefined wartości z wyników. Oznacza to, że jeśli jedna z City właściwości jest nieobecna w dokumencie, zapytanie zwróci tylko jeden wynik, a nie dwa wyniki, z jednym z nich jest null.

Dlaczego

Zawijanie każdego wyniku w dodatkowym obiekcie JSON może spowodować obniżenie wydajności w niektórych scenariuszach, przeładowanie ładunku wyniku JSON i nie jest naturalnym sposobem pracy z usługą Cosmos DB.

Środki zaradcze

Jeśli pobieranie null wartości dla niezdefiniowanych wyników jest ważne dla aplikacji, łączenie undefined wartości null z użyciem nowego EF.Functions.Coalesce operatora:

var users = await context.Customer
    .Select(c => EF.Functions.CoalesceUndefined(c.City, null))
    .ToListAsync();

Niepoprawnie przetłumaczone zapytania nie są już tłumaczone

Problem ze śledzeniem nr 34123

Stare zachowanie

Wcześniej przetłumaczone zapytania EF, takie jak następujące:

var sessions = await context.Sessions
    .Take(5)
    .Where(s => s.Name.StartsWith("f"))
    .ToListAsync();

Jednak tłumaczenie SQL dla tego zapytania było nieprawidłowe:

SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0

W języku SQL klauzula WHERE jest obliczana przed klauzulami OFFSET i LIMIT , ale w powyższym Take zapytaniu LINQ operator pojawia się przed operatorem Where . W rezultacie takie zapytania mogą zwracać nieprawidłowe wyniki.

Nowe zachowanie

Począwszy od programu EF Core 9.0, takie zapytania nie są już tłumaczone i zgłaszany jest wyjątek.

Dlaczego

Nieprawidłowe tłumaczenia mogą powodować uszkodzenie danych dyskretnych, co może powodować trudne do odnalezienia usterki w aplikacji. Program EF zawsze preferuje szybkie działanie w trybie fail-up, zamiast powodować uszkodzenie danych.

Środki zaradcze

Jeśli poprzednie zachowanie jest zadowolony i chcesz wykonać ten sam kod SQL, po prostu zamień kolejność operatorów LINQ:

var sessions = await context.Sessions
    .Where(s => s.Name.StartsWith("f"))
    .Take(5)
    .ToListAsync();

Niestety usługa Cosmos nie obsługuje OFFSET obecnie klauzul i LIMIT w podzapytaniach SQL, co jest odpowiednim tłumaczeniem oryginalnego zapytania LINQ.

Zmiany o niskim wpływie

HasIndex teraz zgłasza zamiast ignorowania

Problem ze śledzeniem nr 34023

Stare zachowanie

Wcześniej wywołania usługi HasIndex zostały zignorowane przez dostawcę usługi EF Cosmos DB.

Nowe zachowanie

Dostawca zgłasza teraz wartość , jeśli HasIndex jest określona.

Dlaczego

W usłudze Cosmos DB wszystkie właściwości są domyślnie indeksowane i nie trzeba określać indeksowania. Chociaż istnieje możliwość zdefiniowania niestandardowych zasad indeksowania, nie jest to obecnie obsługiwane przez platformę EF i można to zrobić za pośrednictwem witryny Azure Portal bez obsługi platformy EF. Ponieważ HasIndex połączenia nie robiły nic, nie są już dozwolone.

Środki zaradcze

Usuń wszystkie wywołania do HasIndex.

IncludeRootDiscriminatorInJsonId zmieniono nazwę na HasRootDiscriminatorInJsonId 9.0.0-rc.2

Problem ze śledzeniem nr 34717

Stare zachowanie

Interfejs IncludeRootDiscriminatorInJsonId API usługi Cosmos został wprowadzony w wersji 9.0.0 rc.1.

Nowe zachowanie

Dla ostatniej wersji programu EF Core 9.0 zmieniono nazwę interfejsu API na HasRootDiscriminatorInJsonId

Dlaczego

Zmieniono nazwę innego powiązanego Includeinterfejsu API na początek Has zamiast , więc nazwa tego interfejsu została również zmieniona na spójność.

Środki zaradcze

Jeśli kod używa interfejsu IncludeRootDiscriminatorInJsonId API, po prostu zmień go na odwołanie HasRootDiscriminatorInJsonId .