Udostępnij za pośrednictwem


Zmiany powodujące niezgodność w programie EF Core 7.0 (EF7)

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

Struktura docelowa

Program EF Core 7.0 jest przeznaczony dla platformy .NET 6. Oznacza to, że istniejące aplikacje przeznaczone dla platformy .NET 6 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 6 lub .NET 7, aby korzystały z programu EF Core 7.0.

Podsumowanie

Zmiana powodująca niezgodność Wpływ
Encrypt wartość domyślna true dla połączeń programu SQL Server Wys.
Niektóre ostrzeżenia ponownie zgłaszają wyjątki domyślnie Wys.
Tabele programu SQL Server z wyzwalaczami lub określonymi kolumnami obliczeniowymi wymagają teraz specjalnej konfiguracji platformy EF Core Wys.
Tabele SQLite z wyzwalaczami AFTER i tabelami wirtualnymi wymagają teraz specjalnej konfiguracji programu EF Core Wys.
Oddzielone zależności relacji opcjonalnych nie są usuwane automatycznie Śred.
Usuwanie kaskadowe jest konfigurowane między tabelami podczas korzystania z mapowania TPT w programie SQL Server Śred.
Większe prawdopodobieństwo zajętych/zablokowanych błędów w programie SQLite, gdy nie jest używane rejestrowanie z wyprzedzeniem zapisu Śred.
Konieczne może być skonfigurowanie kluczowych właściwości za pomocą modułu porównującego wartości dostawcy Niski
Sprawdź ograniczenia i inne aspekty tabeli są teraz skonfigurowane w tabeli Niski
Nawigacje z nowych jednostek do usuniętych jednostek nie są naprawione Niski
Używanie FromSqlRaw metod i powiązanych metod z nieprawidłowego dostawcy zgłasza Niski
Szkielet nie OnConfiguring wywołuje już wywołań IsConfigured Niski

Zmiany o dużym wpływie

Encrypt wartość domyślna true dla połączeń programu SQL Server

Problem ze śledzeniem: SqlClient #1210

Ważne

Jest to poważna zmiana powodująca niezgodność w pakiecie Microsoft.Data.SqlClient . Nie ma nic, co można zrobić w programie EF Core, aby przywrócić lub złagodzić tę zmianę. Prześlij opinię do repozytorium GitHub Microsoft.Data.SqlClient lub skontaktuj się z pomoc techniczna firmy Microsoft Professional, aby uzyskać dodatkowe pytania lub pomoc.

Stare zachowanie

Program SqlClient parametry połączenia używać Encrypt=False domyślnie. Umożliwia to nawiązywanie połączeń na maszynach deweloperskich, na których serwer lokalny nie ma prawidłowego certyfikatu.

Nowe zachowanie

Program SqlClient parametry połączenia używać Encrypt=True domyślnie. To oznacza, że:

  • Serwer musi być skonfigurowany przy użyciu prawidłowego certyfikatu
  • Klient musi ufać temu certyfikatowi

Jeśli te warunki nie zostaną spełnione, zostanie zgłoszony element SqlException . Na przykład:

Połączenie z serwerem zostało pomyślnie nawiązane, ale wystąpił błąd podczas procesu logowania. (dostawca: Dostawca SSL, błąd: 0 — łańcuch certyfikatów został wystawiony przez urząd, który nie jest zaufany).

Dlaczego

Ta zmiana została wprowadzona, aby upewnić się, że domyślnie połączenie jest bezpieczne lub aplikacja nie będzie mogła nawiązać połączenia.

Środki zaradcze

Istnieją trzy sposoby kontynuowania:

  1. Zainstaluj prawidłowy certyfikat na serwerze. Należy pamiętać, że jest to proces zaangażowany i wymaga uzyskania certyfikatu i upewnienia się, że jest podpisany przez urząd zaufany przez klienta.
  2. Jeśli serwer ma certyfikat, ale nie jest zaufany przez klienta, należy TrustServerCertificate=True zezwolić na pomijanie normalnego mechanizmu zaufania.
  3. Jawnie dodaj Encrypt=False do parametry połączenia.

Ostrzeżenie

Opcje 2 i 3 pozostawiają serwer w stanie potencjalnie niezabezpieczonym.

Niektóre ostrzeżenia ponownie zgłaszają wyjątki

Problem ze śledzeniem nr 29069

Stare zachowanie

W programie EF Core 6.0 usterka dostawcy programu SQL Server oznaczała, że niektóre ostrzeżenia skonfigurowane do zgłaszania wyjątków domyślnie były rejestrowane, ale nie zgłaszały wyjątków. Te ostrzeżenia są następujące:

EventId opis
RelationalEventId.AmbientTransactionWarning Aplikacja mogła oczekiwać, że transakcja otoczenia będzie używana, gdy została ona rzeczywiście zignorowana.
RelationalEventId.IndexPropertiesBothMappedAndNotMappedToTable Indeks określa właściwości, z których niektóre są mapowane, a niektóre nie są mapowane na kolumnę w tabeli.
RelationalEventId.IndexPropertiesMappedToNonOverlappingTables Indeks określa właściwości mapowania na kolumny w tabelach nienakładających się.
RelationalEventId.ForeignKeyPropertiesMappedToUnrelatedTables Klucz obcy określa właściwości, które nie są mapowe na powiązane tabele.

Nowe zachowanie

Począwszy od platformy EF Core 7.0, ostrzeżenia te domyślnie powodują zgłoszenie wyjątku.

Dlaczego

Są to problemy, które najprawdopodobniej wskazują błąd w kodzie aplikacji, który powinien zostać rozwiązany.

Środki zaradcze

Rozwiąż podstawowy problem, który jest przyczyną ostrzeżenia.

Alternatywnie można zmienić poziom ostrzeżenia, tak aby był rejestrowany tylko lub całkowicie pomijany. Na przykład:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(RelationalEventId.AmbientTransactionWarning));

Tabele programu SQL Server z wyzwalaczami lub określonymi kolumnami obliczeniowymi wymagają teraz specjalnej konfiguracji platformy EF Core

Problem ze śledzeniem nr 27372

Stare zachowanie

Poprzednie wersje dostawcy programu SQL Server zapisywały zmiany za pomocą mniej wydajnej techniki, która zawsze działała.

Nowe zachowanie

Domyślnie program EF Core zapisuje teraz zmiany za pomocą znacznie bardziej wydajnej techniki; niestety ta technika nie jest obsługiwana w programie SQL Server, jeśli tabela docelowa zawiera wyzwalacze bazy danych lub niektóre typy kolumn obliczeniowych. Aby uzyskać więcej informacji, zobacz dokumentację programu SQL Server.

Dlaczego

Ulepszenia wydajności związane z nową metodą są wystarczająco istotne, aby domyślnie udostępnić je użytkownikom. Jednocześnie szacujemy użycie wyzwalaczy bazy danych lub kolumn obliczeniowych, których dotyczy problem, w aplikacjach EF Core, aby było wystarczająco niskie, że negatywne konsekwencje zmiany powodujące niezgodność są przeważane przez wzrost wydajności.

Środki zaradcze

Począwszy od programu EF Core 8.0, można jawnie skonfigurować użycie klauzuli "OUTPUT". Na przykład:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlOutputClause(false));
}

W programie EF7 lub nowszym, jeśli tabela docelowa ma wyzwalacz, możesz poinformować program EF Core o tym, a program EF powróci do poprzedniej, mniej wydajnej techniki. Można to zrobić, konfigurując odpowiedni typ jednostki w następujący sposób:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.HasTrigger("SomeTrigger"));
}

Należy pamiętać, że wykonanie tej czynności nie powoduje, że program EF Core tworzy wyzwalacz ani nie zarządza nim w żaden sposób — obecnie informuje tylko program EF Core, że wyzwalacze znajdują się w tabeli. W związku z tym można użyć dowolnej nazwy wyzwalacza. Określenie wyzwalacza może służyć do przywracania starego zachowania , nawet jeśli w tabeli nie ma wyzwalacza.

Jeśli większość lub wszystkie tabele mają wyzwalacze, możesz zrezygnować z korzystania z nowszej, wydajnej techniki dla wszystkich tabel modelu przy użyciu następującej konwencji tworzenia modelu:

public class BlankTriggerAddingConvention : IModelFinalizingConvention
{
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder,
        IConventionContext<IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
            if (table != null
                && entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(table.Value) == null)
                && (entityType.BaseType == null
                    || entityType.GetMappingStrategy() != RelationalAnnotationNames.TphMappingStrategy))
            {
                entityType.Builder.HasTrigger(table.Value.Name + "_Trigger");
            }

            foreach (var fragment in entityType.GetMappingFragments(StoreObjectType.Table))
            {
                if (entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(fragment.StoreObject) == null))
                {
                    entityType.Builder.HasTrigger(fragment.StoreObject.Name + "_Trigger");
                }
            }
        }
    }
}

Użyj konwencji dotyczącej elementu DbContext , przesłaniając element ConfigureConventions:

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ => new BlankTriggerAddingConvention());
}

Skutecznie wywołuje HasTrigger to wszystkie tabele modelu, zamiast ręcznie wykonywać je dla każdej tabeli.

Tabele SQLite z wyzwalaczami AFTER i tabelami wirtualnymi wymagają teraz specjalnej konfiguracji programu EF Core

Problem ze śledzeniem nr 29916

Stare zachowanie

Poprzednie wersje dostawcy SQLite zapisywały zmiany za pomocą mniej wydajnej techniki, która zawsze działała.

Nowe zachowanie

Domyślnie program EF Core zapisuje teraz zmiany za pomocą bardziej wydajnej techniki przy użyciu klauzuli RETURNING. Niestety ta technika nie jest obsługiwana w bazie danych SQLite, jeśli tabela docelowa ma wyzwalacze AFTER bazy danych, jest wirtualna lub jeśli są używane starsze wersje sqlite. Aby uzyskać więcej informacji, zobacz dokumentację sqlite.

Dlaczego

Uproszczenia i ulepszenia wydajności związane z nową metodą są na tyle istotne, że ważne jest, aby domyślnie udostępnić je użytkownikom. Jednocześnie szacujemy użycie wyzwalaczy bazy danych i tabel wirtualnych w aplikacjach EF Core, aby było wystarczająco niskie, że negatywne konsekwencje zmiany powodujące niezgodność są przeważane przez wzrost wydajności.

Środki zaradcze

W programie EF Core 8.0 UseSqlReturningClause metoda została wprowadzona w celu jawnego powrotu do starszego, mniej wydajnego kodu SQL. Na przykład:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlReturningClause(false));
}

Jeśli nadal używasz programu EF Core 7.0, można przywrócić stary mechanizm dla całej aplikacji, wstawiając następujący kod w konfiguracji kontekstu:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Zmiany o średnim wpływie

Oddzielone zależności relacji opcjonalnych nie są usuwane automatycznie

Problem ze śledzeniem nr 27217

Stare zachowanie

Relacja jest opcjonalna , jeśli jego klucz obcy jest dopuszczany do wartości null. Ustawienie klucza obcego na wartość null umożliwia istnienie jednostki zależnej bez żadnej powiązanej jednostki głównej. Relacje opcjonalne można skonfigurować tak, aby korzystały z usuwania kaskadowego, chociaż nie jest to ustawienie domyślne.

Opcjonalna zależność może zostać odcięta od podmiotu zabezpieczeń, ustawiając jego klucz obcy na wartość null, lub czyszcząc nawigację do lub z niej. W programie EF Core 6.0 spowoduje to usunięcie zależności, gdy relacja została skonfigurowana do usuwania kaskadowego.

Nowe zachowanie

Począwszy od programu EF Core 7.0, zależne nie jest już usuwane. Należy pamiętać, że jeśli podmiot zabezpieczeń zostanie usunięty, zależne będzie nadal usuwane, ponieważ kaskadowe usunięcia są skonfigurowane dla relacji.

Dlaczego

Zależność może istnieć bez żadnej relacji z podmiotem zabezpieczeń, dlatego zerwanie relacji nie powinno spowodować usunięcia jednostki.

Środki zaradcze

Zależne można jawnie usunąć:

context.Remove(blog);

Można też SaveChanges przesłonić lub przechwycić w celu usunięcia zależności bez odwołania podmiotu zabezpieczeń. Na przykład:

context.SavingChanges += (c, _) =>
    {
        foreach (var entry in ((DbContext)c!).ChangeTracker
            .Entries<Blog>()
            .Where(e => e.State == EntityState.Modified))
        {
            if (entry.Reference(e => e.Author).CurrentValue == null)
            {
                entry.State = EntityState.Deleted;
            }
        }
    };

Usuwanie kaskadowe jest konfigurowane między tabelami podczas korzystania z mapowania TPT w programie SQL Server

Problem ze śledzeniem nr 28532

Stare zachowanie

Podczas mapowania hierarchii dziedziczenia przy użyciu strategii TPT tabela podstawowa musi zawierać wiersz dla każdej zapisanej jednostki, niezależnie od rzeczywistego typu tej jednostki. Usunięcie wiersza w tabeli podstawowej powinno spowodować usunięcie wierszy we wszystkich innych tabelach. Program EF Core konfiguruje w tym celu kaskadowe usuwanie .

W programie EF Core 6.0 usterka dostawcy bazy danych programu SQL Server oznaczała, że te kaskadowe usunięcia nie zostały utworzone.

Nowe zachowanie

Począwszy od programu EF Core 7.0, kaskadowe usunięcia są teraz tworzone dla programu SQL Server tak samo jak zawsze w przypadku innych baz danych.

Dlaczego

Kaskadowe usuwanie z tabeli podstawowej do tabel podrzędnych w tabeli TPT umożliwia usunięcie jednostki przez usunięcie wiersza w tabeli podstawowej.

Środki zaradcze

W większości przypadków ta zmiana nie powinna powodować żadnych problemów. Jednak program SQL Server jest bardzo restrykcyjny, gdy istnieje wiele zachowań kaskadowych skonfigurowanych między tabelami. Oznacza to, że jeśli istnieje istniejąca relacja kaskadowa między tabelami w mapowaniu TPT, program SQL Server może wygenerować następujący błąd:

Microsoft.Data.SqlClient.SqlException: instrukcja DELETE powoduje konflikt z ograniczeniem REFERENCE "FK_Blogs_People_OwnerId". Konflikt wystąpił w bazie danych "Scratch", tabeli "dbo". Blogi", kolumna "OwnerId". Instrukcja została zakończona.

Na przykład ten model tworzy cykl kaskadowych relacji:

[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
    public int ReferencePostId { get; set; }
    public Post ReferencePost { get; set; } = null!;
}

[Table("Posts")]
public class Post
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public string? Content { get; set; }
}

Jedną z tych opcji należy skonfigurować tak, aby nie używać kaskadowych usuwania na serwerze. Aby na przykład zmienić jawną relację:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne(e => e.ReferencePost)
    .WithMany()
    .OnDelete(DeleteBehavior.ClientCascade);

Możesz też zmienić niejawną relację utworzoną dla mapowania TPT:

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne<Post>()
    .WithOne()
    .HasForeignKey<FeaturedPost>(e => e.Id)
    .OnDelete(DeleteBehavior.ClientCascade);

Większe prawdopodobieństwo zajętych/zablokowanych błędów w programie SQLite, gdy nie jest używane rejestrowanie z wyprzedzeniem zapisu

Stare zachowanie

Poprzednie wersje dostawcy SQLite zapisali zmiany za pomocą mniej wydajnej techniki, która była w stanie automatycznie ponowić próbę, gdy tabela została zablokowana/zajęta, a rejestrowanie z wyprzedzeniem zapisu (WAL) nie zostało włączone.

Nowe zachowanie

Domyślnie program EF Core zapisuje teraz zmiany za pomocą bardziej wydajnej techniki przy użyciu klauzuli RETURNING. Niestety ta technika nie jest w stanie automatycznie ponowić próby po zajęciu/zablokowaniu. W aplikacji wielowątkowa (takiej jak aplikacja internetowa) nie korzysta z rejestrowania z wyprzedzeniem zapisu, często występują te błędy.

Dlaczego

Uproszczenia i ulepszenia wydajności związane z nową metodą są na tyle istotne, że ważne jest, aby domyślnie udostępnić je użytkownikom. Bazy danych utworzone przez program EF Core również domyślnie włączają rejestrowanie z wyprzedzeniem zapisu. Zespół SQLite zaleca również domyślne włączanie rejestrowania z wyprzedzeniem zapisu.

Środki zaradcze

Jeśli to możliwe, należy włączyć rejestrowanie z wyprzedzeniem zapisu w bazie danych. Jeśli baza danych została utworzona przez program EF, powinno to już mieć miejsce. Jeśli nie, możesz włączyć rejestrowanie z wyprzedzeniem zapisu, wykonując następujące polecenie.

PRAGMA journal_mode = 'wal';

Jeśli z jakiegoś powodu nie można włączyć rejestrowania z wyprzedzeniem zapisu, można przywrócić stary mechanizm dla całej aplikacji, wstawiając następujący kod w konfiguracji kontekstu:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

Zmiany o niskim wpływie

Konieczne może być skonfigurowanie kluczowych właściwości za pomocą modułu porównującego wartości dostawcy

Problem ze śledzeniem nr 27738

Stare zachowanie

W programie EF Core 6.0 wartości klucza pobrane bezpośrednio z właściwości typów jednostek były używane do porównywania wartości kluczy podczas zapisywania zmian. Spowoduje to użycie dowolnego niestandardowego porównania wartości skonfigurowanego dla tych właściwości.

Nowe zachowanie

Począwszy od programu EF Core 7.0, wartości baz danych są używane do tych porównań. To "po prostu działa" dla zdecydowanej większości przypadków. Jeśli jednak właściwości korzystały z niestandardowego modułu porównania i tego modułu porównującego nie można zastosować do wartości bazy danych, może być potrzebny "moduł porównania wartości dostawcy", jak pokazano poniżej.

Dlaczego

Różne podziały jednostek i dzielenie tabel mogą spowodować mapowanie wielu właściwości na tę samą kolumnę bazy danych i na odwrót. Wymaga to porównania wartości po konwersji na wartość, która będzie używana w bazie danych.

Środki zaradcze

Konfigurowanie porównania wartości dostawcy. Rozważmy na przykład przypadek, w którym obiekt wartości jest używany jako klucz, a moduł porównujący dla tego klucza używa porównań ciągów bez uwzględniania wielkości liter:

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer);

Wartości bazy danych (ciągi) nie mogą bezpośrednio używać porównywacza zdefiniowanego dla BlogKey typów. W związku z tym należy skonfigurować porównanie ciągów bez uwzględniania wielkości liter przez dostawcę:

var caseInsensitiveComparer = new ValueComparer<string>(
    (l, r) => string.Equals(l, r, StringComparison.OrdinalIgnoreCase),
    v => v.ToUpper().GetHashCode(),
    v => v);

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer, caseInsensitiveComparer);

Sprawdź ograniczenia i inne aspekty tabeli są teraz skonfigurowane w tabeli

Problem ze śledzeniem nr 28205

Stare zachowanie

W programie EF Core 6.0 HasCheckConstraintwywołano metody i HasCommentIsMemoryOptimized bezpośrednio w konstruktorze typów jednostek. Na przykład:

modelBuilder
    .Entity<Blog>()
    .HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023");

modelBuilder
    .Entity<Blog>()
    .HasComment("It's my table, and I'll delete it if I want to.");

modelBuilder
    .Entity<Blog>()
    .IsMemoryOptimized();

Nowe zachowanie

Począwszy od programu EF Core 7.0, te metody są zamiast tego wywoływane w konstruktorze tabel:

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023"));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasComment("It's my table, and I'll delete it if I want to."));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.IsMemoryOptimized());

Istniejące metody zostały oznaczone jako Obsolete. Obecnie mają takie samo zachowanie jak nowe metody, ale zostaną usunięte w przyszłej wersji.

Dlaczego

Te aspekty mają zastosowanie tylko do tabel. Nie będą one stosowane do żadnych zamapowanych widoków, funkcji ani procedur składowanych.

Środki zaradcze

Użyj metod konstruktora tabel, jak pokazano powyżej.

Problem ze śledzeniem nr 28249

Stare zachowanie

W programie EF Core 6.0, gdy nowa jednostka jest śledzona z zapytania śledzenia lub dołączając ją do elementu , nawigacje do DbContexti z powiązanych jednostek wDeleted stanienaprawione.

Nowe zachowanie

Począwszy od programu EF Core 7.0, nawigacje do i z Deleted jednostek nie są naprawione.

Dlaczego

Po oznaczeniu jednostki jako Deleted rzadko warto ją skojarzyć z jednostkami, które nie zostały usunięte.

Środki zaradcze

Wykonaj zapytanie lub dołącz jednostki przed oznaczeniem jednostek jako Deletedlub ręcznie ustaw właściwości nawigacji na i z usuniętej jednostki.

Problem ze śledzeniem nr 26502

Stare zachowanie

W programie EF Core 6.0 użycie metody rozszerzenia usługi Azure Cosmos DB podczas korzystania z dostawcy relacyjnego lub metody rozszerzenia relacyjnego FromSqlRaw w przypadku korzystania z dostawcy usługi Azure Cosmos DB FromSqlRaw może dyskretnie zakończyć się niepowodzeniem. Podobnie używanie metod relacyjnych u dostawcy w pamięci jest dyskretnym no-op.

Nowe zachowanie

Począwszy od programu EF Core 7.0, użycie metody rozszerzenia zaprojektowanej dla jednego dostawcy u innego dostawcy zgłosi wyjątek.

Dlaczego

Prawidłowa metoda rozszerzenia musi być używana do prawidłowego działania we wszystkich sytuacjach.

Środki zaradcze

Użyj poprawnej metody rozszerzenia dla używanego dostawcy. Jeśli odwołuje się do wielu dostawców, wywołaj metodę rozszerzenia jako metodę statyczną. Na przykład:

var result = await CosmosQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToListAsync();

Lub:

var result = await RelationalQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToListAsync();

Szkielet nie OnConfiguring wywołuje już wywołań IsConfigured

Problem ze śledzeniem nr 4274

Stare zachowanie

W programie EF Core 6.0 DbContext typ szkieletowy z istniejącej bazy danych zawierał wywołanie metody IsConfigured. Na przykład:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        optionsBuilder.UseNpgsql("MySecretConnectionString");
    }
}

Nowe zachowanie

Począwszy od programu EF Core 7.0, wywołanie metody IsConfigured nie jest już uwzględniane.

Dlaczego

Istnieją bardzo ograniczone scenariusze, w których dostawca bazy danych jest skonfigurowany wewnątrz elementu DbContext w niektórych przypadkach, ale tylko wtedy, gdy kontekst nie jest jeszcze skonfigurowany. Zamiast tego pozostawienie OnConfiguring tutaj sprawia, że bardziej prawdopodobne jest, że parametry połączenia zawierający poufne informacje pozostają w kodzie, pomimo ostrzeżenia czasu kompilacji. W związku z tym dodatkowy bezpieczny i czystszy kod z usunięcia tego elementu został uznany za godny uwagi, zwłaszcza, że --no-onconfiguring flaga (interfejs wiersza polecenia platformy .NET) lub -NoOnConfiguring (konsola programu Visual Studio Menedżer pakietów) może służyć do zapobiegania tworzenia OnConfiguring szkieletów metody i że możliwe do dostosowania szablony istnieją, aby dodać z powrotemIsConfigured, jeśli jest to naprawdę potrzebne.

Środki zaradcze

Dowolny z następujących elementów:

  • Użyj argumentu --no-onconfiguring (interfejs wiersza polecenia platformy .NET) lub -NoOnConfiguring (Visual Studio Menedżer pakietów Console) podczas tworzenia szkieletu z istniejącej bazy danych.
  • Dostosuj szablony T4, aby dodać wywołanie do IsConfiguredmetody .