Łamliwe zmiany w wersji EF Core 9 (EF9)

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:

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

Zmiana powodująca niezgodność Wpływ
wyjątek jest zgłaszany podczas stosowania migracji, jeśli występują oczekujące zmiany modelu Wysoki
Wyjątek jest wyrzucany podczas stosowania migracji w jawnej transakcji Wysoki
Microsoft.EntityFrameworkCore.Design nie znaleziono podczas korzystania z narzędzi EF Średni
EF.Functions.Unhex() teraz zwraca byte[]? Niski
Skompilowane modele odwołują się teraz bezpośrednio do metod konwertera wartości Niski
Zatwierdzono poprawność arności argumentów nulowalności w SqlFunctionExpression Niski
ToString() metoda zwraca teraz pusty ciąg dla null wystąpień Niski
Zależności struktury udostępnionej zostały zaktualizowane do wersji 9.0.x Niski
narzędzia EF nie obsługują już projektów .NET Framework Niski
EF.Constant() i EF.Parameter() nie działają już wewnątrz skompilowanych zapytań Niski
Niektóre NoTrackingWithIdentityResolution zapytania są teraz zabronione dla kolekcji JSON Niski
Wszystkie oczekujące migracje są wykonywane w ramach jednej transakcji Niski
Interfejsy API kolekcji prymitywnych zostały zastąpione Niski
IndexOf SQL Server teraz propaguje wartości null Niski

Zmiany o dużym wpływie

Wyjątek jest zgłaszany podczas stosowania migracji, jeśli istnieją oczekujące zmiany modelu

Śledzenie problemu #33732

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.UtcNowlub Guid.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 .
  • 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))
  • 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, IDesignTimeDbContextFactory należy zaimplementować w projekcie zawierającym DbContextelement:

      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

Zgłoszenie nr 33456

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

Zgłoszenie nr 18773

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 zapytaniu AsNoTrackingWithIdentityResolution() 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.