Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ta strona dokumentuje zmiany w interfejsie API i zachowaniu, które mogą potencjalnie przerwać istniejące aplikacje aktualizowane z 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 łamiące zgodność w EF Core 6
Struktura docelowa
EF Core 9 jest przeznaczony dla .NET 8. Oznacza to, że istniejące aplikacje docelowe .NET 8 mogą nadal to robić. Aplikacje przeznaczone dla starszych wersji .NET, .NET Core i .NET Framework będą musiały być skierowane na .NET 8 lub .NET 9, aby korzystać z EF Core 9.
Podsumowanie
Uwaga
Jeśli używasz Azure Cosmos DB, zobacz osobną sekcję poniżej dotyczącą Azure Cosmos DB i niekompatybilnych zmian.
Zmiany o dużym wpływie
Wyjątek jest zgłaszany podczas stosowania migracji, jeśli istnieją oczekujące zmiany modelu
Stare zachowanie
Jeśli model ma oczekujące zmiany w porównaniu z ostatnią migracją, nie są one stosowane z resztą migracji, gdy wywoływana jest Migrate.
Nowe zachowanie
Od EF Core 9.0, jeśli model ma oczekujące zmiany w porównaniu z ostatnią migracją, zgłaszany jest wyjątek, gdy wywoływane są dotnet ef database update, Migrate lub MigrateAsync.
Model kontekstu "DbContext" ma oczekujące zmiany. Dodaj nową migrację przed zaktualizowaniem bazy danych. Ten wyjątek można pominąć lub zarejestrować, przekazując identyfikator zdarzenia "RelationalEventId.PendingModelChangesWarning" do metody "ConfigureWarnings" w metodzie "DbContext.OnConfiguring" lub "AddDbContext".
Dlaczego
Zapominanie o dodaniu nowej migracji po wprowadzeniu zmian modelu jest typowym błędem, który może być trudny do zdiagnozowania w niektórych przypadkach. Nowy wyjątek gwarantuje, że model aplikacji jest zgodny z bazą danych po zastosowaniu migracji.
Środki zaradcze
Istnieje kilka typowych sytuacji, w których można zgłosić ten wyjątek:
W ogóle nie ma żadnych migracji. Jest to typowe, gdy baza danych jest aktualizowana za pomocą innych środków.
- Zarządzanie: jeśli nie zamierzasz korzystać z migracji do zarządzania schematem bazy danych, usuń wywołanie lub Migrate, w przeciwnym razie dodaj migrację.
Istnieje co najmniej jedna migracja, ale brakuje migawki modelu. Jest to typowe dla migracji utworzonych ręcznie.
- Łagodzenie: Dodaj nową migrację za pomocą narzędzi EF, co spowoduje zaktualizowanie migawki modelu.
Model nie został zmodyfikowany przez dewelopera, ale jest wbudowany w sposób niedeterministyczny powodujący, że program EF wykrywa go w miarę modyfikacji. Jest to powszechne, gdy
new DateTime(),DateTime.Now,DateTime.UtcNowlubGuid.NewGuid()są używane w obiektach dostarczonych do HasData.- Mitigacja: Dodaj nową migrację, sprawdź jej zawartość, aby zlokalizować przyczynę, zastępując dane dynamiczne statyczną, zakodowaną na stałe wartością w modelu. Migracja powinna zostać ponownie utworzona po naprawieniu modelu. Jeśli dane dynamiczne muszą być używane do rozmieszczania, rozważ użycie nowego wzorca rozmieszczania zamiast HasData.
Ostatnia migracja została utworzona dla innego dostawcy niż ten, którego zastosowano do zastosowania migracji.
-
ograniczania ryzyka: jest to nieobsługiwany scenariusz. Ostrzeżenie można pominąć przy użyciu poniższego fragmentu kodu, ale ten scenariusz prawdopodobnie przestanie działać w przyszłej wersji platformy EF Core. Zalecanym rozwiązaniem jest wygenerowanie oddzielnego zestawu migracji dla każdego dostawcyprzez
.
-
ograniczania ryzyka: jest to nieobsługiwany scenariusz. Ostrzeżenie można pominąć przy użyciu poniższego fragmentu kodu, ale ten scenariusz prawdopodobnie przestanie działać w przyszłej wersji platformy EF Core. Zalecanym rozwiązaniem jest wygenerowanie oddzielnego zestawu migracji dla każdego dostawcyprzez
Migracje są generowane, modyfikowane lub wybierane dynamicznie przez zastąpienie niektórych usług EF.
-
Łagodzenie: w tym przypadku ostrzeżenie jest fałszywie dodatnie i powinno zostać pominięte.
options.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
-
Łagodzenie: w tym przypadku ostrzeżenie jest fałszywie dodatnie i powinno zostać pominięte.
Używasz ASP.NET Core Identity i zmieniasz opcje wpływające na model, takie jak:
.AddDefaultIdentity<ApplicationUser>(options => { options.Stores.SchemaVersion = IdentitySchemaVersions.Version2; options.Stores.MaxLengthForKeys = 256; options.SignIn.RequireConfirmedAccount = false; })pl-PL: Działania zaradcze: W celu zapewnienia, że opcje są stosowane spójnie, aplikacja musi być określona jako projekt startowy podczas uruchamiania narzędzi EF lub, alternatywnie,
IDesignTimeDbContextFactorynależy zaimplementować w projekcie zawierającymDbContextelement:public class DatabaseContextDesignTimeFactory : IDesignTimeDbContextFactory<DatabaseContext> { public DatabaseContext CreateDbContext(string[] args) { var services = new ServiceCollection(); AddIdentity(services); var serviceProvider = services.BuildServiceProvider(); var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>(); optionsBuilder.UseApplicationServiceProvider(serviceProvider); optionsBuilder.UseSqlServer(); return new DatabaseContext(optionsBuilder.Options); } public static IServiceCollection AddIdentity(IServiceCollection services) { services.AddDefaultIdentity<ApplicationUser>(options => { options.Stores.SchemaVersion = IdentitySchemaVersions.Version2; options.Stores.MaxLengthForKeys = 256; options.SignIn.RequireConfirmedAccount = false; }) .AddRoles<IdentityRole>() .AddEntityFrameworkStores<DatabaseContext>(); return services; } }
Jeśli twój scenariusz nie mieści się w żadnym z powyższych przypadków i dodanie nowej migracji powoduje utworzenie tej samej migracji za każdym razem lub pustą migrację, a wyjątek jest nadal zgłaszany, utwórz mały projekt reprodukcji i udostępnij go zespołowi EF w nowym zgłoszeniu.
Wyjątek występuje podczas stosowania migracji w jawnej transakcji
Śledzenie problemu #17578
Stare zachowanie
Aby zastosować migracje w sposób odporny, często używany był następujący wzorzec:
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
await dbContext.Database.MigrateAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
});
Nowe zachowanie
Począwszy od programu EF Core 9.0, wywołania Migrate i MigrateAsync uruchamiają transakcję i wykonują polecenia przy użyciu ExecutionStrategy, a jeśli aplikacja używa powyższego wzorca, zgłaszany jest wyjątek:
Wygenerowano błąd związany z ostrzeżeniem 'Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning': transakcja została uruchomiona przed zastosowaniem migracji. Uniemożliwia to uzyskanie blokady bazy danych, dlatego baza danych nie będzie chroniona przed współbieżnymi aplikacjami migracji. Transakcje i strategia wykonywania są już zarządzane przez EF zgodnie z potrzebami. Usuń transakcję zewnętrzną. Ten wyjątek można pominąć lub zarejestrować, przekazując identyfikator zdarzenia "RelationalEventId.MigrationsUserTransactionWarning" do metody "ConfigureWarnings" w metodzie "DbContext.OnConfiguring" lub "AddDbContext".
Dlaczego
Użycie transakcji jawnej uniemożliwia uzyskanie blokady bazy danych, dlatego baza danych nie będzie chroniona przed równoczesnymi aplikacjami migracji, ogranicza również program EF w zakresie zarządzania transakcjami wewnętrznie.
Środki zaradcze
Jeśli istnieje tylko jedno wywołanie bazy danych wewnątrz transakcji, usuń transakcję zewnętrzną i ExecutionStrategy:
await dbContext.Database.MigrateAsync(cancellationToken);
W przeciwnym razie, jeśli scenariusz wymaga jawnej transakcji i masz inny mechanizm, aby zapobiec współbieżnym aplikacjom migracji, zignoruj ostrzeżenie:
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
Zmiany o średnim wpływie
Microsoft.EntityFrameworkCore.Design nie można odnaleźć podczas korzystania z narzędzi EF
problem ze śledzeniem #35265
Stare zachowanie
Wcześniej narzędzia EF wymagały odwoływania się do Microsoft.EntityFrameworkCore.Design w następujący sposób.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Nowe zachowanie
Począwszy od zestawu .NET SDK 9.0.200 podczas wywoływania narzędzia EF zgłaszany jest wyjątek.
Nie można załadować pliku lub zestawu "Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null". W systemie nie można odnaleźć określonego pliku.
Dlaczego
Narzędzia EF opierały się na nieudokumentowanym zachowaniu zestawu SDK .NET, które powodowało uwzględnienie zasobów prywatnych w wygenerowanym pliku .deps.json. Rozwiązano ten problem w sdk#45259. Niestety, zmiana w EF, aby to uwzględnić, nie spełnia kryterium serwisowego dla EF 9.0.x, więc zostanie to naprawione w EF 10.
Środki zaradcze
Aby obejść ten problem przed wydaniem programu EF 10, możesz oznaczyć odwołanie do biblioteki Design jako możliwą do opublikowania:
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
Spowoduje to uwzględnienie go w wygenerowanym pliku .deps.json, ale skutkiem ubocznym jest kopiowanie Microsoft.EntityFrameworkCore.Design.dll do folderów wyjściowych i publikacyjnych.
Zmiany o niskim wpływie
EF.Functions.Unhex() teraz zwraca byte[]?
Problem ze śledzeniem nr 33864
Stare zachowanie
Funkcja EF.Functions.Unhex() była wcześniej oznaczona adnotacją, aby zwracać 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 rezultacie Unhex() zwrócił null w tych przypadkach, co było w niezgodzie 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 null-forgiving, aby zapewnić, ż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 wyniku funkcji Unhex().
Interfejsy API kolekcji typów prostych zostały zastąpione
Stare zachowanie
W programie EF Core 8 następujące interfejsy API były używane do porównywania i serializacji JSON kolekcji typów prostych:
ListComparer<TElement>NullableValueTypeListComparer<TElement>ObjectListComparer<TElement>JsonCollectionReaderWriter<TCollection, TConcreteCollection, TElement>JsonNullableStructCollectionReaderWriter<TCollection, TConcreteCollection, TElement>
Nowe zachowanie
Począwszy od wersji EF Core 9.0 te interfejsy API zostały zastąpione przez interfejsy API wyspecjalizowane dla typu elementu kolekcji:
| EF Core 8 API | EF Core 9 API |
|---|---|
ListComparer<TElement> |
ListOfValueTypesComparer<TConcreteList, TElement> dla nienullowalnych typów wartości lub ListOfReferenceTypesComparer<TConcreteList, TElement> dla typów referencyjnych |
NullableValueTypeListComparer<TElement> |
ListOfNullableValueTypesComparer<TConcreteList, TElement> |
ObjectListComparer<TElement> |
ListOfReferenceTypesComparer<TConcreteList, TElement> |
JsonCollectionReaderWriter<TCollection, TConcreteCollection, TElement> |
JsonCollectionOfStructsReaderWriter<TConcreteCollection, TElement> lub JsonCollectionOfReferencesReaderWriter<TConcreteCollection, TElement> |
JsonNullableStructCollectionReaderWriter<TCollection, TConcreteCollection, TElement> |
JsonCollectionOfNullableStructsReaderWriter<TConcreteCollection, TElement> |
Dlaczego
Infrastruktura kolekcji typów prostych została skonsolidowana między dostawcami relacyjnymi i Azure Cosmos DB. Nowe interfejsy API używają dokładnego konkretnego typu kolekcji, tworzą migawki i rozróżniają typy wartości inne niż null, typy wartości dopuszczające wartość null oraz typy odwołań. Umożliwia to obsługę kolekcji zagnieżdżonych i tylko do odczytu.
Środki zaradcze
Kod, który bezpośrednio używa jednego z usuniętych interfejsów API, musi użyć zamiennika odpowiedniego dla typu elementu. Podaj konkretny typ kolekcji, taki jak List<int>, jako TConcreteList lub TConcreteCollection, i typ elementu jako TElement.
IndexOf SQL Server teraz propaguje wartości null
Stare zachowanie
Wcześniej, gdy SQL Server tłumaczył IndexOf z pustym ciągiem wyszukiwania, zwracał 0 nawet wtedy, gdy wyszukiwany ciąg to null.
Nowe zachowanie
Począwszy od programu EF Core 9.0 SQL Server zwraca wartość null dla IndexOf, gdy wyszukiwany ciąg to null. Jest to zgodne z tłumaczeniem używanym przez sqlite.
Dlaczego
Nowe tłumaczenie jest zgodne ze standardową propagacją wartości null i nie traktuje już ciągu null jako zawierającego pusty ciąg pod indeksem zero.
Środki zaradcze
Aby zachować poprzednie zachowanie, należy jawnie obsługiwać wartość null w zapytaniu:
var indexes = context.Entities
.Select(e => e.NullableString == null ? 0 : e.NullableString.IndexOf(string.Empty));
Skompilowane modele odwołują się teraz bezpośrednio do metod konwertera wartości
Problem ze śledzeniem nr 35033
Stare zachowanie
Wcześniej, w przypadku używania konwerterów wartości z skompilowanymi modelami (przy użyciu dotnet ef dbcontext optimize), program EF odwołuje się do typu konwertera i wszystko działało poprawnie.
public sealed class BooleanToCharConverter() : ValueConverter<bool, char>(v => ConvertToChar(v), v => ConvertToBoolean(v))
{
public static readonly BooleanToCharConverter Default = new();
private static char ConvertToChar(bool value) // Private method
=> value ? 'Y' : 'N';
private static bool ConvertToBoolean(char value) // Private method
=> value == 'Y';
}
Nowe zachowanie
Począwszy od programu EF Core 9.0, program EF generuje kod, który bezpośrednio odwołuje się do samych metod konwersji. Jeśli te metody są prywatne, kompilacja zakończy się niepowodzeniem.
Dlaczego
Ta zmiana była konieczna do obsługi funkcji NativeAOT.
Środki zaradcze
Ustaw metody, do których odwołuje się konwertery wartości, publiczne lub wewnętrzne zamiast prywatne.
Sprawdzono poprawność liczby argumentów nullowalności dla 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 EF Core 9.0, EF Core zgłasza teraz wyjątek, jeśli liczba argumentów i propagacja wartości null nie są zgodne.
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 dla argumentu nullowalności.
ToString() metoda zwraca teraz pusty ciąg dla null wystąpień
Problem ze śledzeniem nr 33941
Stare zachowanie
Wcześniej EF zwracało niespójne wyniki dla metody ToString(), gdy wartość argumentu wynosiła null. Na przykład dla właściwości ToString() z wartością bool? zwróconą jako null, ale w przypadku wyrażeń innych niż właściwość null, których wartość była bool?, zwrócono null. Zachowanie było również niespójne dla innych typów danych, np. ToString() wyliczenie null wartości zwróciło pusty ciąg.
Nowe zachowanie
Począwszy od EF Core 9.0, metoda ToString() stale zwraca pusty ciąg we wszystkich przypadkach, gdy wartość argumentu to null.
Dlaczego
Stare zachowanie było niespójne w różnych typach danych i sytuacjach, a także nie było zgodne z zachowaniem języka C#.
Środki zaradcze
Aby przywrócić stare zachowanie, zapisz odpowiednio zapytanie:
var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());
Zależności struktury udostępnionej zostały zaktualizowane do wersji 9.0.x
Stare zachowanie
Aplikacje korzystające z pakietu SDK Microsoft.NET.Sdk.Web i które są ukierunkowane na net8.0 rozwiązują pakiety takie jak System.Text.Json, Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Logging i Microsoft.Extensions.DependencyModel ze współdzielonego środowiska, więc te biblioteki zwykle nie będą wdrażane z aplikacją.
Nowe zachowanie
Chociaż EF Core 9.0 nadal obsługuje platformę net8.0, teraz odwołuje się do wersji 9.0.x System.Text.Json, Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Logging i Microsoft.Extensions.DependencyModel. Aplikacje celujące w net8.0 nie będą mogły korzystać z platformy współdzielonej, aby uniknąć wdrażania tych bibliotek.
Dlaczego
Pasujące wersje zależności zawierają najnowsze poprawki zabezpieczeń i ich użycie upraszcza model obsługi dla platformy EF Core.
Środki zaradcze
Aby uzyskać poprzednie zachowanie, zmień aplikację, aby celowała w net9.0.
Narzędzia EF nie obsługują już projektów platformy .NET Framework
Problem ze śledzeniem nr 37745
Stare zachowanie
Wcześniej narzędzia EF Core (narzędzia CLI i narzędzia konsoli Menedżer pakietów) współpracowały z projektami przeznaczonymi dla platformy .NET Framework.
Nowe zachowanie
Począwszy od programu EF Core 9.0, narzędzia EF Core nie działają już z projektami przeznaczonymi dla platformy .NET Framework. Narzędzia generują błąd, gdy projekt startowy jest przeznaczony dla platformy .NET Framework.
Dlaczego
Bieżąca wersja narzędzi EF Core współpracuje ze wszystkimi obsługiwanymi wersjami programu EF Core i nie ma już żadnych obsługiwanych wersji programu EF Core, które działają na platformie .NET Framework.
Środki zaradcze
Zaktualizuj projekt do docelowej wersji .NET (np. .NET 8 lub nowszej). Jeśli projekt jest obecnie przeznaczony dla .NET Framework, zobacz przewodnik porting aby uzyskać informacje na temat migracji do .NET.
EF.Constant() i EF.Parameter() nie działają już wewnątrz skompilowanych zapytań
Problem ze śledzeniem nr 33674
Stare zachowanie
W EF Core 8 Constant i Parameter mogły być używane wewnątrz skompilowanych zapytań (CompileQuery i CompileAsyncQuery):
var lookbackDays = 7;
var compiledQuery = EF.CompileAsyncQuery(
(AppDbContext db) => db.Blogs
.Where(b => b.PublishedOn >= DateTime.Today.AddDays(EF.Constant(-lookbackDays))));
Nowe zachowanie
Począwszy od programu EF Core 9.0, użycie Constant lub Parameter wewnątrz skompilowanego zapytania zgłasza błąd InvalidCastException:
Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'System.Linq.Expressions.ParameterExpression'.
Dlaczego
Wewnętrzna implementacja Constant została zmieniona, aby uniknąć pełnej kompilacji zapytania dla każdej innej stałej wartości. Poprzednia implementacja wprowadziła stałe węzły na wczesnym etapie potoku zapytań (przed buforowaniem zapytań), co powodowało kosztowne chybienia pamięci podręcznej za każdym razem, gdy do EF.Constant() przekazana była inna wartość. Nowa implementacja przetwarza te metody na późniejszym etapie, który jest niezgodny z skompilowanymi zapytaniami.
Środki zaradcze
Usuń wywołanie Constant lub Parameter z skompilowanego zapytania lub zatrzymaj użycie skompilowanego zapytania dla tego konkretnego zapytania. Należy pamiętać, że usunięcie EF.Constant() powoduje wysłanie wartości jako parametru SQL, a nie w postaci stałej, co może mieć wpływ na wydajność planu zapytania.
Niektóre NoTrackingWithIdentityResolution zapytania są teraz zabronione dla kolekcji JSON
Problem ze śledzeniem nr 33073
Stare zachowanie
Wcześniej użycie AsNoTrackingWithIdentityResolution (lub ustawienie NoTrackingWithIdentityResolution) z zapytaniami zawierającymi kolekcje jednostek mapowanych w formacie JSON może dyskretnie spowodować nieprawidłowe wyniki lub uszkodzenie danych, w zależności od kolejności przetwarzania jednostek podczas materializacji. Ponadto takie zapytania mogą zgłaszać nieprzydatny Invalid token type: 'StartObject' wyjątek w niektórych scenariuszach.
Nowe zachowanie
Począwszy od programu EF Core 9.0, program EF Core ogranicza użycie AsNoTrackingWithIdentityResolution niektórych wzorców zapytań kolekcji JSON, aby zapobiec uszkodzeniu danych dyskretnych:
- Jeśli wystąpienia jednostek w kolekcji JSON zostaną zmaterializowane w kolejności, która może spowodować uszkodzenie danych, program EF Core zgłasza wyjątek, który nakazuje użytkownikowi użycie innego zachowania śledzenia.
- Używanie operatorów LINQ (takich jak
OrderBy,Where,Skip,Takeitp.) bezpośrednio w nawigacji kolekcji JSON w zapytaniuAsNoTrackingWithIdentityResolution()jest teraz zabronione. Na przykład następujące zapytanie zgłosi wyjątek:
var blogs = await context.Blogs
.AsNoTrackingWithIdentityResolution()
.Select(b => new
{
Blog = b,
TopPosts = b.JsonPosts.OrderBy(p => p.Rating).Take(3).ToList()
})
.ToListAsync();
Dlaczego
Połączenie AsNoTrackingWithIdentityResolution i kolekcji JSON może po cichu powodować tworzenie niepoprawnie zmaterializowanych obiektów ze względu na sposób strumieniowego przesyłania danych JSON z bazy danych: zagnieżdżone dołączenia w JSON są częścią materializacji obiektu nadrzędnego, zamiast być materializowane oddzielnie. Samodzielny mechanizm śledzenia zmian używany do rozpoznawania tożsamości obiektów opiera się na wartościach kluczy w celu deduplikacji wystąpień encji, ale gdy operatory LINQ są stosowane do kolekcji JSON, EF Core nie może niezawodnie przekazać tych wartości kluczy do materializatora, co skutkuje encjami z kluczami o wartości null i potencjalnym uszkodzeniem danych.
Środki zaradcze
Jeśli wymagane jest rozpoznawanie tożsamości, użyj standardowego zapytania śledzącego:
var blogs = await context.Blogs
.AsTracking()
.Select(b => new
{
Blog = b,
TopPosts = b.JsonPosts.OrderBy(p => p.Rating).Take(3).ToList()
})
.ToListAsync();
Jeśli nie potrzebujesz rozpoznawania tożsamości, użyj AsNoTracking zamiast tego:
var blogs = await context.Blogs
.AsNoTracking()
.Select(b => new
{
Blog = b,
TopPosts = b.JsonPosts.OrderBy(p => p.Rating).Take(3).ToList()
})
.ToListAsync();
Wszystkie oczekujące migracje są wykonywane w ramach jednej transakcji
Problem ze śledzeniem nr 34439
Stare zachowanie
Wcześniej program EF Core (domyślnie) opakowuje każdą migrację we własnej transakcji podczas stosowania migracji.
Nowe zachowanie
Od wersji EF Core 9.0 wszystkie oczekujące migracje zostają zastosowane w ramach jednej transakcji jako część mechanizmu blokowania migracji. Jeśli migracja nie powiedzie się, cała transakcja zostanie wycofana. To zachowanie zostało przywrócone w programie EF Core 10.
Dlaczego
Zastosowanie wszystkich migracji w jednej transakcji gwarantuje, że baza danych jest w pełni up-to-date lub pozostawiona bez zmian, jeśli wystąpi błąd, unikając stanów pośrednich.
Środki zaradcze
Jeśli potrzebujesz zachowania transakcji dla każdej migracji w EF Core 9, zaktualizuj do EF Core 10, który przywraca obejmowanie każdej migracji osobną transakcją.
Azure Cosmos DB zmiany niekompatybilne
Dużo pracy włożono w ulepszenie dostawcy Azure Cosmos DB w wersji 9.0. Zmiany obejmują szereg ważnych zmian powodujących istotne niezgodności; jeśli aktualizujesz 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 |
Wysoki |
Właściwość id domyślnie nie zawiera już rozróżniacza. |
Wysoki |
właściwość id JSON jest mapowana do klucza |
Wysoki |
| Sync we/wy za pośrednictwem dostawcy Azure Cosmos DB nie jest już obsługiwany | Średni |
| Zapytania SQL muszą teraz bezpośrednio projektować wartości JSON | Średni |
| Niezdefiniowane wyniki są teraz automatycznie filtrowane z wyników zapytania | Średni |
| Niepoprawnie przetłumaczone zapytania nie są już tłumaczone | Średni |
HasIndex teraz zgłasza zamiast ignorowania |
Niski |
IncludeRootDiscriminatorInJsonId zmieniono nazwę na HasRootDiscriminatorInJsonId po wersji 9.0.0-rc.2 |
Niski |
| Wersja Newtonsoft.Json została zaktualizowana z 10.0.2 do 13.0.1 | 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
Od wersji EF Core 9.0, właściwość dyskryminująca nazywa się teraz domyślnie $type. Jeśli masz istniejące dokumenty w Azure Cosmos DB z poprzednich wersji programu EF, które używają starego nazewnictwa Discriminator, to po uaktualnieniu do programu EF 9.0 zapytania na te dokumenty nie powiodą 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 .NET obsługuje również polimorfizm, używając $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 sposobem złagodzenia tego problemu jest po prostu skonfigurowanie nazwy właściwości dyskryminującej na Discriminator, dokładnie tak jak przed użyciem HasDiscriminator.
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.
Alternatywnie, jeśli chcesz zaktualizować wszystkie dokumenty, aby używać nowego $type nazewnictwa, aby nie potrzebujesz już powyższej konfiguracji, możesz to zrobić przy użyciu zestawu SDK Azure Cosmos DB. Poniższy kod zmienia nazwę właściwości Discriminator na $type we wszystkich dokumentach w kontenerze:
using Microsoft.Azure.Cosmos;
using System.Text.Json.Nodes;
// Replace with your Cosmos DB connection string.
var cosmosClient = new CosmosClient(connectionString);
var container = cosmosClient.GetContainer("myDatabase", "myContainer");
using var feedIterator = container.GetItemQueryIterator<JsonObject>("SELECT * FROM c WHERE IS_DEFINED(c.Discriminator)");
while (feedIterator.HasMoreResults)
{
foreach (var item in await feedIterator.ReadNextAsync())
{
if (item.ContainsKey("Discriminator"))
{
item["$type"] = item["Discriminator"]!.DeepClone();
item.Remove("Discriminator");
// The id and partition key are required for ReplaceItemAsync.
// Adjust the partition key extraction to match your container's partition key path.
var id = item["id"]!.GetValue<string>();
var partitionKey = new PartitionKey(item["myPartitionKeyProperty"]!.GetValue<string>());
await container.ReplaceItemAsync(item, id, partitionKey);
}
}
}
Uwaga
Zastąp myPartitionKeyProperty nazwą właściwości, którą skonfigurowano jako klucz partycji w kontenerze. Jeśli kontener używa dokumentu id jako klucza partycji, użyj id również wartości klucza partycji.
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ć wartość Blog|8.
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 wartość 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 Azure Cosmos DB z poprzednich wersji programu EF, posiadają one wartość dyskryminującą we właściwości JSON id, a po uaktualnieniu do programu EF 9.0 zapytania dotyczące tych dokumentów się nie powiodą.
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, to pozwalało na posiadanie zarówno Blog, jak i Post, które miały właściwość Id zawierającą wartość 8, w tym samym kontenerze i partycji. Jest to lepsze dopasowanie do wzorców modelowania danych w bazach danych relacyjnych, w których 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 Azure Cosmos DB NoSQL, zamiast odpowiadać oczekiwaniom użytkowników pochodzących z relacyjnych baz danych. Ponadto posiadanie wartości dyskryminującej we właściwości id 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 pochodzące z typów .NET.
Środki zaradcze
Najprostszym środkiem zaradczym jest po prostu skonfigurowanie frameworka EF w celu uwzględnienia dyskryminatora we właściwości JSON id, tak jak wcześniej przy użyciu HasDiscriminatorInJsonId. 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.
Alternatywnie, jeśli chcesz zaktualizować wszystkie istniejące dokumenty, aby usunąć wartość dyskryminującą z id właściwości, aby nie potrzebujesz już powyższej konfiguracji, możesz to zrobić przy użyciu zestawu SDK Azure Cosmos DB. 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 klucza w ramach tej samej partycji kontenera.
Azure Cosmos DB nie zezwala na aktualizowanie id właściwości istniejącego dokumentu. Zamiast tego należy usunąć stary dokument i utworzyć nowy z zaktualizowanym iddokumentem . Następujący kod wykonuje tę migrację:
using Microsoft.Azure.Cosmos;
using System.Text.Json.Nodes;
// Replace with your Cosmos DB connection string.
var cosmosClient = new CosmosClient(connectionString);
var container = cosmosClient.GetContainer("myDatabase", "myContainer");
// Replace with the name of the property configured as the partition key in your container.
// If the partition key path is /id, set this to "id".
const string partitionKeyProperty = "myPartitionKeyProperty";
using var feedIterator = container.GetItemQueryIterator<JsonObject>("SELECT * FROM c");
while (feedIterator.HasMoreResults)
{
foreach (var item in await feedIterator.ReadNextAsync())
{
var oldId = item["id"]!.GetValue<string>();
var separatorIndex = oldId.IndexOf('|');
if (separatorIndex != -1)
{
var newId = oldId[(separatorIndex + 1)..];
// Capture the partition key value before updating the id.
// When partitionKeyProperty is "id", this captures the old id for the delete operation.
var partitionKeyForDelete = new PartitionKey(item[partitionKeyProperty]!.GetValue<string>());
// Update the id to the new value without the discriminator prefix.
item["id"] = JsonValue.Create(newId);
// When partitionKeyProperty is "id", read it again after the update to get the new id for the create operation.
var partitionKeyForCreate = new PartitionKey(item[partitionKeyProperty]!.GetValue<string>());
// Azure Cosmos DB does not allow changing the id - create a new document and delete the old one.
await container.CreateItemAsync(item, partitionKeyForCreate);
await container.DeleteItemAsync<JsonObject>(oldId, partitionKeyForDelete);
}
}
}
Uwaga
Ustaw partitionKeyProperty nazwę właściwości skonfigurowanej jako klucz partycji w kontenerze. Gdy ścieżka klucza partycji to /id, przykład poprawnie używa starej id wartości operacji usuwania i nowej id wartości dla operacji tworzenia, ponieważ partitionKeyProperty jest odczytywany zarówno przed, jak i po aktualizacji item["id"].
Jeśli dojdzie do awarii między wywołaniami CreateItemAsync i DeleteItemAsync, możesz skończyć z oboma dokumentami. Podczas ponownego uruchamiania migracji obsłuż to, przechwytując 409 Conflict z CreateItemAsync i przechodząc do wywołania DeleteItemAsync w celu usunięcia starego dokumentu.
Właściwość id JSON jest mapowana na klucz
Problem ze śledzeniem nr 34179
Stare zachowanie
Wcześniej EF tworzył właściwość cienia zamapowaną na właściwość id w JSON, chyba że jedna z właściwości została zamapowana na id w sposób jawny.
Nowe zachowanie
Od EF Core 9, właściwość klucza zostanie odwzorowana na właściwość JSON id zgodnie z konwencją, jeśli to możliwe. Oznacza to, że właściwość klucza nie będzie już utrwalana w dokumencie pod inną nazwą o tej samej wartości, więc kod inny niż EF korzystający z dokumentów i opierając się na tej właściwości nie będzie już działać poprawnie.
Dlaczego
Program EF 9.0 ogólnie zmienił mapowanie tak, aby był bardziej zgodny z typowymi praktykami i oczekiwaniami Azure Cosmos DB NoSQL. Nie jest powszechne przechowywanie wartości klucza dwa razy w dokumencie.
Środki zaradcze
Jeśli chcesz zachować zachowanie programu EF Core 8, najprostszym rozwiązaniem jest użycie HasShadowId, nowej opcji konfiguracji, która została wprowadzona w tym celu.
modelBuilder.Entity<Session>().HasShadowId();
Wykonanie tej czynności dla wszystkich typów jednostek najwyższego poziomu sprawi, że program EF będzie zachowywał się tak jak wcześniej. Możesz też zastosować go do wszystkich typów jednostek w modelu z jednym wywołaniem przy użyciu polecenia HasShadowIds:
modelBuilder.HasShadowIds();
Alternatywnie, jeśli chcesz zastosować nowe zachowanie EF 9.0, a istniejące dokumenty zawierają właściwość klucza przechowywaną oddzielnie (np. jako "Id": 8 obok "id": "Blog|8"), możesz usunąć nadmiarową właściwość klucza przy użyciu zestawu SDK Azure Cosmos DB. Jeśli przeprowadzasz również migrację formatu właściwości id (usuwając prefiks rozróżnika), możesz połączyć oba kroki, jak pokazano powyżej w migracji właściwości id. Poniższy przykład usuwa nadmiarową "Id" właściwość, jeśli migracja id została już wykonana:
using Microsoft.Azure.Cosmos;
using System.Text.Json.Nodes;
// Replace with your Cosmos DB connection string.
var cosmosClient = new CosmosClient(connectionString);
var container = cosmosClient.GetContainer("myDatabase", "myContainer");
// Adjust "Id" to match your entity's key property name.
using var feedIterator = container.GetItemQueryIterator<JsonObject>("SELECT * FROM c WHERE IS_DEFINED(c.Id)");
while (feedIterator.HasMoreResults)
{
foreach (var item in await feedIterator.ReadNextAsync())
{
item.Remove("Id");
var id = item["id"]!.GetValue<string>();
// Adjust the partition key extraction to match your container's partition key path.
var partitionKey = new PartitionKey(item["myPartitionKeyProperty"]!.GetValue<string>());
await container.ReplaceItemAsync(item, id, partitionKey);
}
}
Uwaga
Zastąp Id nazwą właściwości klucza encji, a myPartitionKeyProperty nazwą właściwości skonfigurowanej jako klucz partycji w swoim kontenerze.
Zmiany o średnim wpływie
Synchronizacja we/wy za pośrednictwem dostawcy 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, powodowało, że EF Core blokował synchronicznie przy użyciu .GetAwaiter().GetResult() podczas wykonywania wywołań asynchronicznych względem Azure Cosmos DB SDK. Może to spowodować zakleszczenie.
Nowe zachowanie
Od wersji EF Core 9.0, EF domyślnie zgłasza wyjątek przy próbie użycia synchronicznego we/wy. Komunikat o wyjątku to "Azure Cosmos DB nie obsługuje synchronicznych operacji we/wy. Pamiętaj, aby używać tylko metod asynchronicznych i prawidłowo na nie oczekiwać podczas korzystania z Entity Framework Core do dostępu do Azure Cosmos DB. Zobacz https://aka.ms/ef-cosmos-nosync , aby uzyskać więcej informacji.
Dlaczego
Blokowanie synchroniczne w przypadku metod asynchronicznych może spowodować zakleszczenie, a zestaw SDK Azure Cosmos DB obsługuje tylko asynchroniczne metody.
Ś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 Azure Cosmos DB, ponieważ nie jest to obsługiwane przez zestaw SDK 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 Azure Cosmos DB opakowuje każdy wynik w obiekt 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 Azure Cosmos DB zwraca wartości bezpośrednio, bez opakowania.
[
"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
Opakowywanie każdego wyniku w dodatkowym obiekcie JSON może spowodować obniżenie wydajności w niektórych scenariuszach, zwiększa objętość ładunku JSON i nie jest naturalną metodą pracy z Azure 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 Azure Cosmos DB opakowuje każdy wynik w obiekt 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), zwracano pusty dokument, a program EF zwracałby null dla tego wyniku.
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 Azure Cosmos DB zwraca wartości bezpośrednio, bez opakowania.
[
"Berlin",
"México D.F."
]
Zachowanie Azure Cosmos DB polega na automatycznym filtrowaniu wartości undefined z wyników; oznacza to, że jeśli jedna z właściwości City jest nieobecna w dokumencie, zapytanie zwróci tylko jeden wynik, a nie dwa wyniki, z jednym null.
Dlaczego
Opakowywanie każdego wyniku w dodatkowym obiekcie JSON może spowodować obniżenie wydajności w niektórych scenariuszach, zwiększa objętość ładunku JSON i nie jest naturalną metodą pracy z Azure Cosmos DB.
Środki zaradcze
Jeśli dla aplikacji ważne jest uzyskanie null wartości dla niezdefiniowanych wyników, scal undefined wartości do null korzystając z nowego operatora EF.Functions.Coalesce.
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 EF tłumaczyło zapytania, 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 SQL klauzula WHERE jest obliczana przed klauzulami OFFSET i LIMIT, ale w zapytaniu LINQ powyżej operator Take 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 byłeś zadowolony z poprzedniego działania i chcesz wykonać ten sam SQL, po prostu zamień kolejność operatorów LINQ.
var sessions = await context.Sessions
.Where(s => s.Name.StartsWith("f"))
.Take(5)
.ToListAsync();
Niestety, Azure Cosmos DB obecnie nie obsługuje OFFSET i LIMIT klauzul w podzapytaniach SQL, co wymaga odpowiedniego tłumaczenia 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 Azure 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 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 po 9.0.0-rc.2
Problem ze śledzeniem nr 34717
Stare zachowanie
Interfejs IncludeRootDiscriminatorInJsonId API 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
Inny powiązany interfejs API został przemianowany tak, aby zaczynać się od Has zamiast Include, dlatego ten interfejs również został przemianowany dla zachowania spójności.
Środki zaradcze
Jeśli kod używa interfejsu IncludeRootDiscriminatorInJsonId API, po prostu zmień go na referencję HasRootDiscriminatorInJsonId.
Zaktualizowano odwołanie do wersji Newtonsoft.Json z wersji 10.0.2 na wersję 13.0.1.
Stare zachowanie
Dostawca usługi Cosmos odwołuje się do pliku Newtonsoft.Json w wersji 10.0.2.
Nowe zachowanie
Począwszy od programu EF Core 9.0, dostawca usługi Cosmos odwołuje się do pliku Newtonsoft.Json w wersji 13.0.1.
Dlaczego
Wcześniej odwołana wersja pliku Newtonsoft.Json ma znane luki w zabezpieczeniach. Wersja została zaktualizowana, aby uniknąć zależności od wersji pakietu, który ma znane problemy z bezpieczeństwem.
Środki zaradcze
Uaktualnienie do wersji Newtonsoft.Json 13.0.1 nie powinno powodować problemów w większości przypadków. Jeśli aplikacja korzysta bezpośrednio z pliku Newtonsoft.Json i korzysta z określonej starszej wersji, możesz zaktualizować aplikację tak, aby mogła być zgodna z wersją Newtonsoft.Json 13.0.1 lub nowszą. Szczegółowe informacje o zmianach między wersjami można znaleźć w informacjach o wydaniach Newtonsoft.Json.