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:
- Istotne zmiany w programie EF Core 8
- Istotne zmiany w programie EF Core 7
- Zmiany powodujące niezgodność w programie EF Core 6
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.
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 Discriminator
wartość , 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|8
wartość .
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 Include
interfejsu 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
.