Zmiany powodujące niezgodność zawarte w programie EF Core 3.x

Następujące zmiany interfejsu API i zachowania mogą uszkodzić istniejące aplikacje podczas uaktualniania ich do wersji 3.x.

Podsumowanie

Zmiana powodująca niezgodność Wpływ
Zapytania LINQ nie są już oceniane na kliencie Wysoki
Narzędzie wiersza polecenia platformy EF Core dotnet ef nie jest już częścią zestawu .NET Core SDK Wysoki
DetectChanges honoruje wartości kluczy generowanych przez bazę danych Wysoki
Zmieniono nazwę funkcji: FromSql, ExecuteSql i ExecuteSqlAsync Wysoki
Typy zapytań są konsolidowane przy użyciu typów jednostek Wysoki
Platforma Entity Framework Core nie jest już częścią platformy udostępnionej ASP.NET Core Średni
Usunięcia kaskadowe są teraz wykonywane natychmiast domyślnie Średni
Chętne ładowanie powiązanych encji odbywa się teraz w jednym zapytaniu Średni
Funkcja DeleteBehavior.Restrict ma semantykę czystszą Średni
Zmieniono interfejs API konfiguracji dla relacji typu należącego Średni
Każda właściwość używa niezależnego generowania kluczy całkowitych w pamięci Średni
Zapytania bez śledzenia nie wykonują już rozpoznawania tożsamości Średni
Zmiany interfejsu API metadanych Średni
Zmiany w interfejsie API metadanych dla konkretnego dostawcy Średni
Parametr UseRowNumberForPaging został usunięty Średni
Metody FromSql nie można skomponować, jeśli jest używana z procedurą składowaną Średni
Metody FromSql można stosować tylko na korzeniach zapytań Niski
Tymczasowe wartości klucza nie są już ustawiane na wystąpienia jednostek Niski
Jednostki zależne dzielące tabelę z głównym podmiotem są teraz opcjonalne Niski
Wszystkie jednostki udostępniające tabelę z kolumną tokenu współbieżności muszą mapować ją na właściwość Niski
Nie można wykonywać zapytań dotyczących jednostek należących do właściciela bez użycia zapytania śledzenia Niski
Właściwości dziedziczone z niemapowanych typów są teraz mapowane na jedną kolumnę dla wszystkich typów pochodnych Niski
Konwencja dotycząca właściwości klucza obcego nie jest już zgodna z nazwą właściwości głównej Niski
Połączenie z bazą danych jest zamykane, gdy nie jest już używane, zanim zakończy się TransactionScope Niski
Pola kopii zapasowej są używane domyślnie Niski
Zgłaszaj, czy znaleziono wiele zgodnych pól kopii zapasowych Niski
Nazwy właściwości tylko dla pól powinny być zgodne z nazwą pola Niski
AddDbContext/AddDbContextPool nie wywołuje już funkcji AddLogging i AddMemoryCache Niski
AddEntityFramework* dodaje funkcję IMemoryCache z limitem rozmiaru Niski
Funkcja DbContext.Entry wykonuje teraz lokalną funkcję DetectChanges Niski
Klucze ciągów i tablic bajtów nie są domyślnie generowane przez klienta Niski
ILoggerFactory jest teraz usługą o określonym zakresie Niski
Proxies ładowane z opóźnieniem nie zakładają już, że właściwości nawigacyjne są w pełni załadowane Niski
Nadmierne tworzenie wewnętrznych dostawców usług jest teraz domyślnie błędem Niski
Nowe zachowanie dla HasOne/HasMany wywołany z jednym ciągiem Niski
Typ zwracany dla kilku metod asynchronicznych został zmieniony z Task na ValueTask Niski
Adnotacja Relational:TypeMapping jest teraz po prostu TypeMapping Niski
ToTable dla typu pochodnego zgłasza wyjątek Niski
Program EF Core nie wysyła już pragma dla wymuszania klucza FK SQLite Niski
Microsoft.EntityFrameworkCore.Sqlite teraz zależy od SQLitePCLRaw.bundle_e_sqlite3 Niski
Wartości guid są teraz przechowywane jako TEKST w sqlite Niski
Wartości znaków są teraz przechowywane jako TEKST w sqlite Niski
Identyfikatory migracji są teraz generowane przy użyciu niezmiennego kalendarza kultury Niski
Informacje/metadane rozszerzenia zostały usunięte z rozszerzenia IDbContextOptionsExtension Niski
LogQueryPossibleExceptionWithAggregateOperator został przemianowany Niski
Uściślij interfejs API dla nazw ograniczeń klucza obcego Niski
IRelationalDatabaseCreator.HasTables/HasTablesAsync zostały upublicznione Niski
Microsoft.EntityFrameworkCore.Design jest teraz pakietem DevelopmentDependency Niski
SQLitePCL.raw zaktualizowano do wersji 2.0.0 Niski
NetTopologySuite zaktualizowano do wersji 2.0.0 Niski
Element Microsoft.Data.SqlClient jest używany zamiast Elementu System.Data.SqlClient Niski
Należy skonfigurować wiele niejednoznacznych relacji odwołujących się do siebie Niski
Gdy parametr DbFunction.Schema jest pusty lub ma wartość null, jest konfigurowany tak, aby znajdować się w domyślnym schemacie modelu Niski
Program EF Core 3.0 jest przeznaczony dla platformy .NET Standard 2.1, a nie .NET Standard 2.0 Przywrócono
Wykonywanie zapytania jest rejestrowane na poziomie debugowania przywrócono

Zmiany o dużym wpływie

Zapytania LINQ nie są już oceniane na kliencie

Problem ze śledzeniem nr 14935Zobacz również problem nr 12795

Stare zachowanie

Przed wersją 3.0, gdy program EF Core nie mógł przekonwertować wyrażenia będącego częścią zapytania na SQL lub parametr, automatycznie ewaluował wyrażenie na kliencie. Domyślnie ocena klienta potencjalnie kosztownych wyrażeń wyłącznie wywoływała ostrzeżenie.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core zezwala na to, aby wyrażenia w projekcji na najwyższym poziomie (ostatnie wywołanie Select() w kontekście zapytania) były oceniane po stronie klienta. Jeśli wyrażenia w żadnej innej części zapytania nie mogą być konwertowane na sql lub parametr, zgłaszany jest wyjątek.

Dlaczego

Automatyczna ocena klienta zapytań umożliwia wykonywanie wielu zapytań, nawet jeśli nie można przetłumaczyć ważnych części zapytań. To zachowanie może spowodować nieoczekiwane i potencjalnie szkodliwe zachowanie, które może stać się widoczne tylko w środowisku produkcyjnym. Na przykład, warunek w wywołaniu Where(), którego nie można przetłumaczyć, może spowodować, że wszystkie wiersze z tabeli zostaną przeniesione z serwera bazy danych, a filtr zostanie zastosowany po stronie klienta. Taka sytuacja może być łatwo niewykryta, jeśli tabela zawiera tylko kilka wierszy podczas programowania, ale mocno uderza, gdy aplikacja przechodzi do środowiska produkcyjnego, gdzie tabela może zawierać miliony wierszy. Ostrzeżenia dotyczące oceny klienta okazały się również zbyt łatwe do zignorowania podczas opracowywania.

Poza tym automatyczna ocena klienta może prowadzić do problemów, w których poprawa tłumaczenia zapytań dla określonych wyrażeń spowodowała niezamierzone zmiany prowadzące do niezgodności między wydaniami.

Środki zaradcze

Jeśli nie można w pełni przetłumaczyć zapytania, należy napisać zapytanie ponownie w formie, którą można przetłumaczyć, lub użyć AsEnumerableAsync(), ToListAsync() lub podobnego sposobu, aby jawnie przywrócić dane do klienta, gdzie można je dalej przetwarzać przy użyciu LINQ-to-Objects.

Zmiany o średnim wpływie

Platforma Entity Framework Core nie jest już częścią platformy udostępnionej ASP.NET Core

Śledzenie ogłoszeń kwestii nr 325

Stare zachowanie

Przed ASP.NET Core 3.0, po dodaniu odwołania do pakietu Microsoft.AspNetCore.App lub Microsoft.AspNetCore.All, dołączane było EF Core oraz niektórzy dostawcy danych EF Core, tacy jak dostawca SQL Server.

Nowe zachowanie

Począwszy od wersji 3.0, platforma udostępniona ASP.NET Core nie obejmuje platformy EF Core ani żadnych dostawców danych platformy EF Core.

Dlaczego

Przed tą zmianą, uzyskanie EF Core wymagało różnych kroków, w zależności od tego, czy aplikacja docelowa była skierowana na ASP.NET Core i SQL Server, czy nie. Ponadto uaktualnienie ASP.NET Core wymusiło uaktualnienie platformy EF Core i dostawcy programu SQL Server, co nie zawsze jest pożądane.

Dzięki tej zmianie proces uzyskiwania EF Core jest taki sam dla wszystkich dostawców, obsługiwanych implementacji .NET i rodzajów aplikacji. Deweloperzy mogą teraz dokładnie kontrolować, kiedy EF Core i dostawcy danych EF Core są uaktualniani.

Środki zaradcze

Aby użyć programu EF Core w aplikacji ASP.NET Core 3.0 lub dowolnej innej obsługiwanej aplikacji, jawnie dodaj odwołanie do pakietu do dostawcy bazy danych EF Core, którego będzie używać aplikacja.

Narzędzie wiersza polecenia platformy EF Core dotnet ef nie jest już częścią zestawu .NET Core SDK

Problem ze śledzeniem nr 14016

Stare zachowanie

Przed 3.0 dotnet ef narzędzie zostało dołączone do zestawu .NET Core SDK i było łatwo dostępne do użycia z poziomu wiersza polecenia z dowolnego projektu bez konieczności wykonywania dodatkowych kroków.

Nowe zachowanie

Począwszy od wersji 3.0, zestaw .NET SDK nie zawiera dotnet ef narzędzia, więc zanim będzie można go użyć, musisz jawnie zainstalować go jako narzędzie lokalne lub globalne.

Dlaczego

Ta zmiana pozwala nam rozpowszechniać i aktualizować dotnet ef jako zwykłe narzędzie interfejsu wiersza polecenia platformy .NET w pakiecie NuGet, zgodnie z faktem, że program EF Core 3.0 jest również zawsze dystrybuowany jako pakiet NuGet.

Środki zaradcze

Aby móc zarządzać migracjami lub szkieletami DbContextprogramu , zainstaluj dotnet-ef jako narzędzie globalne:

dotnet tool install --global dotnet-ef

Narzędzie lokalne można również uzyskać podczas przywracania zależności projektu, który deklaruje je jako zależność narzędziową, używając pliku manifestu narzędzia.

Zmiany o niskim wpływie

Zmieniono nazwy metod FromSql, ExecuteSql i ExecuteSqlAsync.

Śledzenie problemu nr 10996

Ważne

ExecuteSqlCommand i ExecuteSqlCommandAsync są przestarzałe. Zamiast tego użyj tych metod.

Stare zachowanie

Przed programem EF Core 3.0 te nazwy metod zostały przeciążone do pracy z normalnym ciągiem lub ciągiem, który powinien być interpolowany do języka SQL i parametrów.

Nowe zachowanie

Począwszy od programu EF Core 3.0, użyj polecenia FromSqlRaw, ExecuteSqlRawi ExecuteSqlRawAsync , aby utworzyć sparametryzowane zapytanie, w którym parametry są przekazywane oddzielnie od ciągu zapytania. Na przykład:

context.Products.FromSqlRaw(
    "SELECT * FROM Products WHERE Name = {0}",
    product.Name);

Użyj FromSqlInterpolated, ExecuteSqlInterpolatedi ExecuteSqlInterpolatedAsync , aby utworzyć sparametryzowane zapytanie, w którym parametry są przekazywane jako część ciągu zapytania interpolowanego. Na przykład:

context.Products.FromSqlInterpolated(
    $"SELECT * FROM Products WHERE Name = {product.Name}");

Należy pamiętać, że oba powyższe zapytania spowodują wygenerowanie tego samego sparametryzowanego kodu SQL z tymi samymi parametrami SQL.

Dlaczego

Takie przeciążenia metody ułatwiają przypadkowe wywołanie metody nieprzetworzonego ciągu, gdy intencją było wywołanie metody ciągów interpolowanych i odwrotnie. Może to spowodować, że zapytania nie są sparametryzowane, gdy powinny być.

Środki zaradcze

Zmień na nowe nazwy metod.

Metoda FromSql, jeśli jest używana z procedurą składowaną, nie może być złożona

Problem ze śledzeniem nr 15392

Stare zachowanie

Przed wersją EF Core 3.0 metoda FromSql próbowała wykryć, czy przekazany SQL można było na nim budować. Przeprowadzono ocenę klienta, gdy SQL nie była komponowalna, jak procedura składowana. Poniższe zapytanie działało, uruchamiając procedurę składowaną na serwerze i wykonując operację FirstOrDefault po stronie klienta.

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").FirstOrDefault();

Nowe zachowanie

Począwszy od programu EF Core 3.0, program EF Core nie spróbuje przeanalizować bazy danych SQL. Więc jeśli komponujesz po FromSqlRaw/FromSqlInterpolated, program EF Core utworzy SQL, tworząc podzapytanie. Dlatego jeśli używasz procedury składowanej z kompozycją, otrzymasz wyjątek dotyczący nieprawidłowej składni SQL.

Dlaczego

Program EF Core 3.0 nie obsługuje automatycznej oceny klienta, ponieważ był podatny na błędy, jak wyjaśniono tutaj.

Środki zaradcze

Jeśli używasz procedury składowanej w metodzie FromSqlRaw/FromSqlInterpolated, wiesz, że nie można jej skomponować, więc możesz dodać AsEnumerable/AsAsyncEnumerable bezpośrednio po wywołaniu metody FromSql, aby uniknąć jakiejkolwiek kompozycji po stronie serwera.

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").AsEnumerable().FirstOrDefault();

Metody FromSql można określić tylko dla korzeni zapytań

Problem ze śledzeniem nr 15704

Stare zachowanie

Przed EF Core 3.0, metodę FromSql można było określić w dowolnym miejscu w zapytaniu.

Nowe zachowanie

Począwszy od EF Core 3.0, nowe metody FromSqlRaw i FromSqlInterpolated (które zastępują FromSql) można określić tylko dla korzeni zapytania, tj. bezpośrednio na DbSet<>. Próba określenia ich w dowolnym miejscu spowoduje błąd kompilacji.

Dlaczego

Określanie FromSql gdziekolwiek indziej niż na DbSet nie miało żadnego dodatkowego znaczenia ani wartości dodanej i mogło powodować niejasności w niektórych scenariuszach.

Środki zaradcze

FromSql wywołania powinny być przeniesione bezpośrednio na DbSet, którego dotyczą.

Zapytania bez śledzenia nie wykonują już rozpoznawania tożsamości

Śledzenie problemu nr 13518

Stare zachowanie

Przed programem EF Core 3.0 to samo wystąpienie jednostki będzie używane dla każdego wystąpienia jednostki o danym typie i identyfikatorze. To odpowiada sposobowi działania zapytań śledzących. Poniższe przykładowe zapytanie:

var results = await context.Products.Include(e => e.Category).AsNoTracking().ToListAsync();

zwraca to samo Category wystąpienie dla każdego Product , który jest skojarzony z daną kategorią.

Nowe zachowanie

Począwszy od programu EF Core 3.0, różne wystąpienia jednostek zostaną utworzone, gdy jednostka o danym typie i identyfikatorze zostanie napotkana w różnych miejscach na zwracanym grafie. Na przykład powyższe zapytanie zwróci nowe Category wystąpienie dla każdego Product nawet wtedy, gdy dwa produkty są skojarzone z tą samą kategorią.

Dlaczego

Rozpoznawanie tożsamości (czyli określenie, że jednostka ma ten sam typ i identyfikator co wcześniej napotkana jednostka), dodaje dodatkowe obciążenie związane z wydajnością i pamięcią. Zwykle jest to sprzeczne z tym, dlaczego zapytania bez śledzenia są używane w pierwszej kolejności. Ponadto podczas gdy rozpoznawanie tożsamości może być czasami przydatne, nie jest konieczne, jeśli jednostki mają być serializowane i wysyłane do klienta, co jest powszechne w przypadku zapytań bez śledzenia.

Środki zaradcze

Użyj zapytania śledzenia, jeśli jest wymagane rozpoznawanie tożsamości.

Tymczasowe wartości klucza nie są już ustawiane na wystąpienia jednostek

Problem ze śledzeniem nr 12378

Stare zachowanie

Przed programem EF Core 3.0 wartości tymczasowe zostały przypisane do wszystkich właściwości klucza, które później miały rzeczywistą wartość wygenerowaną przez bazę danych. Zazwyczaj te wartości tymczasowe były dużą liczbą ujemną.

Nowe zachowanie

Począwszy od wersji 3.0, EF Core przechowuje tymczasową wartość klucza jako część informacji o śledzeniu encji, nie zmieniając samej właściwości klucza.

Dlaczego

Ta zmiana została wprowadzona, aby zapobiec niepoprawnemu zamienieniu się wartości kluczy tymczasowych w stałe, gdy jednostka, która była wcześniej śledzona przez instancję DbContext, zostanie przeniesiona do innej instancji DbContext.

Środki zaradcze

Aplikacje, które przypisują wartości klucza głównego do kluczy obcych w celu tworzenia powiązań między encjami, mogą zależeć od starego zachowania, jeśli klucze główne są generowane przez system i należą do encji w Added stanie. Można tego uniknąć, wykonując następujące czynności:

  • Nieużywaj kluczy generowanych przez magazyn.
  • Ustawianie właściwości nawigacji w celu tworzenia relacji zamiast ustawiania wartości klucza obcego.
  • Uzyskaj rzeczywiste wartości klucza tymczasowego z informacji śledzenia jednostki. Na przykład funkcja zwróci wartość tymczasową, context.Entry(blog).Property(e => e.Id).CurrentValue mimo że blog.Id sama nie została ustawiona.

DetectChanges respektuje wartości kluczy generowanych przez magazyn

Śledzenie zgłoszenia nr 14616

Stare zachowanie

Przed EF Core 3.0, nieśledzona jednostka znaleziona przez DetectChanges będzie śledzona w stanie Added i wstawiona jako nowy wiersz po wywołaniu SaveChanges.

Nowe zachowanie

Od EF Core 3.0, jeśli encja używa wygenerowanych wartości klucza i ustawiono jakąkolwiek wartość, encja będzie śledzona jako w stanie Modified. Oznacza to, że zakłada się, że istnieje wiersz dla jednostki i zostanie zaktualizowany po SaveChanges wywołaniu. Jeśli wartość klucza nie jest ustawiona lub typ jednostki nie używa wygenerowanych kluczy, nowa jednostka będzie nadal śledzona tak jak Added w poprzednich wersjach.

Dlaczego

Ta zmiana została wprowadzona, aby ułatwić i bardziej spójną pracę z odłączonymi grafami encji podczas korzystania z kluczy generowanych przez magazyn.

Środki zaradcze

Ta zmiana może spowodować przerwanie aplikacji, jeśli typ jednostki jest skonfigurowany do używania wygenerowanych kluczy, ale wartości kluczy są jawnie ustawiane dla nowych wystąpień. Poprawka polega na jawnym skonfigurowaniu właściwości klucza, aby nie używać wygenerowanych wartości. Na przykład za pomocą płynnego interfejsu API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .ValueGeneratedNever();

Lub z adnotacjami danych:

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }

Usunięcia kaskadowe są teraz wykonywane natychmiast domyślnie

Problem ze śledzeniem nr 10114

Stare zachowanie

Przed wersją 3.0, EF Core stosował akcje kaskadowe (usuwanie jednostek zależnych po usunięciu wymaganego obiektu głównego lub zerwaniu relacji z wymaganym obiektem głównym) dopiero po wywołaniu funkcji SaveChanges.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core stosuje akcje kaskadowe natychmiast po wykryciu warunku wyzwalania. Na przykład wywołanie context.Remove() w celu usunięcia głównej encji spowoduje, że wszystkie wymagane zależności będące w śledzeniu zostaną natychmiast ustawione na Deleted.

Dlaczego

Ta zmiana została wprowadzona w celu ulepszenia środowiska dla scenariuszy wiązania i inspekcji danych, w których ważne jest, aby zrozumieć, które jednostki zostaną usunięte przedSaveChanges wywołaniem.

Środki zaradcze

Poprzednie zachowanie można przywrócić za pomocą ustawień w systemie context.ChangeTracker. Na przykład:

context.ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
context.ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges;

Śledzenie problemu nr 18022

Stare zachowanie

Przed wersją 3.0, ładowanie z wyprzedzeniem nawigacji kolekcji za pośrednictwem operatorów Include powodowało wygenerowanie wielu zapytań w relacyjnej bazie danych, po jednym dla każdej powiązanej klasy jednostki.

Nowe zachowanie

Począwszy od wersji 3.0, EF Core generuje pojedyncze zapytanie z JOIN-ami w relacyjnych bazach danych.

Dlaczego

Wydawanie wielu zapytań w celu zaimplementowania pojedynczego zapytania LINQ spowodowało wiele problemów, w tym obniżoną wydajność, ponieważ konieczne były liczne interakcje z bazą danych, a także problemy z koherencją danych, ponieważ każde zapytanie mogło obserwować inny stan bazy danych.

Środki zaradcze

Chociaż technicznie nie jest to zmiana powodująca niezgodność, może to mieć znaczący wpływ na wydajność aplikacji, gdy pojedyncze zapytanie zawiera dużą liczbę operatorów Include w nawigacji kolekcji. Zobacz ten komentarz, aby uzyskać więcej informacji i przeformułować zapytania w bardziej wydajny sposób.

**

Funkcja DeleteBehavior.Restrict ma semantykę czystszą

Śledzenie zgłoszenia nr 12661

Stare zachowanie

Przed 3.0 DeleteBehavior.Restrict utworzono klucze obce w bazie danych za pomocą Restrict semantyki, ale także zmieniono poprawkę wewnętrzną w sposób nieoczywisty.

Nowe zachowanie

Począwszy od wersji 3.0, DeleteBehavior.Restrict zapewnia, że klucze obce są tworzone z semantyką Restrict — to znaczy, bez kaskadowych operacji i zgłaszania wyjątków przy naruszeniu ograniczeń — bez wpływu na wewnętrzne uzupełnienie w EF.

Dlaczego

Ta zmiana została wprowadzona, aby poprawić doświadczenie użytkowania DeleteBehavior w intuicyjny sposób, bez nieoczekiwanych skutków ubocznych.

Środki zaradcze

Poprzednie zachowanie można przywrócić przy użyciu polecenia DeleteBehavior.ClientNoAction.

Typy zapytań są konsolidowane przy użyciu typów jednostek

Problem ze śledzeniem nr 14194

Stare zachowanie

Przed programem EF Core 3.0 typy zapytań były sposobem wykonywania zapytań dotyczących danych, które nie definiują klucza podstawowego w sposób ustrukturyzowany. Oznacza to, że typ zapytania był używany do mapowania typów jednostek bez kluczy (najprawdopodobniej z widoku, ale prawdopodobnie z tabeli), podczas gdy zwykły typ jednostki był używany, gdy klucz był dostępny (bardziej prawdopodobne z tabeli, ale prawdopodobnie z widoku).

Nowe zachowanie

Typ zapytania staje się teraz tylko typem jednostki bez klucza podstawowego. Typy jednostek bez klucza mają taką samą funkcjonalność jak typy zapytań w poprzednich wersjach.

Dlaczego

Ta zmiana została wprowadzona w celu zmniejszenia nieporozumień związanych z celem typów zapytań. W szczególności są to typy jednostek bez klucza i są one z natury tylko do odczytu z tego powodu, ale nie powinny być używane tylko dlatego, że typ jednostki musi być tylko do odczytu. Są one podobnie często przypisywane do widoków, ale jest to tylko dlatego, że widoki często nie definiują kluczy.

Środki zaradcze

Następujące części interfejsu API są teraz przestarzałe:

  • ModelBuilder.Query<>() — Zamiast tego ModelBuilder.Entity<>().HasNoKey() należy wywołać funkcję , aby oznaczyć typ jednostki jako bez kluczy. Nadal nie zostanie to skonfigurowane zgodnie z konwencją, aby uniknąć błędnej konfiguracji, gdy klucz podstawowy jest oczekiwany, ale nie jest zgodny z konwencją.
  • DbQuery<> - Zamiast tego DbSet<> należy użyć.
  • DbContext.Query<>() - Zamiast tego DbContext.Set<>() należy użyć.
  • IQueryTypeConfiguration<TQuery> - Zamiast tego IEntityTypeConfiguration<TEntity> należy użyć.

Uwaga

Ze względu na problem w wersji 3.x podczas wykonywania zapytań dotyczących jednostek bez klucza, które mają wszystkie właściwości ustawione na null, zwrócony zostanie null zamiast jednostki. Jeśli ten problem dotyczy również Twojego scenariusza, dodaj logikę do obsługi null w wynikach.

Zmienił się API konfiguracji dla relacji typu posiadanego

Problem ze śledzeniem #12444Problem ze śledzeniem #9148Problem ze śledzeniem #14153

Stare zachowanie

Przed programem EF Core 3.0 konfiguracja relacji własności została wykonana bezpośrednio po wywołaniu OwnsOne lub OwnsMany .

Nowe zachowanie

Począwszy od programu EF Core 3.0, istnieje teraz płynny interfejs API umożliwiający skonfigurowanie właściwości nawigacji dla właściciela przy użyciu polecenia WithOwner(). Na przykład:

modelBuilder.Entity<Order>.OwnsOne(e => e.Details).WithOwner(e => e.Order);

Konfiguracja odnosząca się do relacji między właścicielem a podwładnym powinna być teraz powiązana w łańcuch po WithOwner(), podobnie jak konfiguracja innych relacji. Mimo że konfiguracja samego typu własności nadal będzie łańcuchowa po OwnsOne()/OwnsMany(). Na przykład:

modelBuilder.Entity<Order>.OwnsOne(e => e.Details, eb =>
    {
        eb.WithOwner()
            .HasForeignKey(e => e.AlternateId)
            .HasConstraintName("FK_OrderDetails");

        eb.ToTable("OrderDetails");
        eb.HasKey(e => e.AlternateId);
        eb.HasIndex(e => e.Id);

        eb.HasOne(e => e.Customer).WithOne();

        eb.HasData(
            new OrderDetails
            {
                AlternateId = 1,
                Id = -1
            });
    });

Ponadto wywołanie Entity(), HasOne() lub Set() z obiektem docelowym typu właścicielskiego spowoduje teraz zgłoszenie wyjątku.

Dlaczego

Ta zmiana została wprowadzona w celu utworzenia czystszego rozdzielenia między skonfigurowaniem samego typu własności a relacją z typem własności. To z kolei eliminuje niejednoznaczność i zamieszanie wokół metod takich jak HasForeignKey.

Środki zaradcze

Zmień konfigurację relacji typu własności, aby używać nowej powierzchni interfejsu API, jak pokazano w powyższym przykładzie.

Jednostki zależne udostępniające tabelę jednostce nadrzędnej są teraz opcjonalne

Problem ze śledzeniem nr 9005

Stare zachowanie

Rozważ następujący model :

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public OrderDetails Details { get; set; }
}

public class OrderDetails
{
    public int Id { get; set; }
    public string ShippingAddress { get; set; }
}

Przed EF Core 3.0, jeśli OrderDetails jest własnością Order lub jest jawnie zamapowany do tej samej tabeli, instancja OrderDetails była zawsze wymagana przy dodawaniu nowego elementu Order.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core umożliwia dodanie Order bez OrderDetails, mapując wszystkie właściwości OrderDetails z wyjątkiem klucza podstawowego do kolumn dopuszczających wartości null. Podczas zapytań EF Core, ustawia OrderDetails na null, jeśli któraś z wymaganych właściwości nie ma wartości lub jeżeli nie ma innych wymaganych właściwości poza kluczem podstawowym, a wszystkie właściwości są null.

Środki zaradcze

Jeśli model ma tabelę zależną z wszystkimi opcjonalnymi kolumnami, ale nawigacja wskazująca na nią nie powinna być null, należy zmodyfikować aplikację, aby obsłużyła przypadki, gdy nawigacja jest null. Jeśli nie jest to możliwe, do typu jednostki powinna zostać dodana wymagana właściwość lub co najmniej jedna właściwość powinna mieć przypisaną wartość inną niż null.

Wszystkie jednostki udostępniające tabelę z kolumną tokenu współbieżności powinny przypisać ją do właściwości

Problem ze śledzeniem nr 14154

Stare zachowanie

Rozważ następujący model :

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public byte[] Version { get; set; }
    public OrderDetails Details { get; set; }
}

public class OrderDetails
{
    public int Id { get; set; }
    public string ShippingAddress { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>()
        .Property(o => o.Version).IsRowVersion().HasColumnName("Version");
}

Przed EF Core 3.0, jeśli OrderDetails jest własnością Order lub jawnie odwzorowany do tej samej tabeli, aktualizacja tylko OrderDetails nie spowoduje zaktualizowania wartości Version i następna aktualizacja zakończy się niepowodzeniem.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core propaguje nową wartość Version do Order, jeśli Order jest właścicielem OrderDetails. W przeciwnym razie podczas walidacji modelu jest zgłaszany wyjątek.

Dlaczego

Ta zmiana została wprowadzona, aby uniknąć nieaktualnej wartości tokenu współbieżności, gdy zostanie zaktualizowana tylko jedna z jednostek zamapowanych na tę samą tabelę.

Środki zaradcze

Wszystkie jednostki współużytkujące tabelę muszą zawierać właściwość zamapowaną do kolumny tokenu współbieżności. Istnieje możliwość utworzenia jednego w stanie cienia:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<OrderDetails>()
        .Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");
}

Nie można wykonywać zapytań dotyczących jednostek należących do właściciela bez użycia zapytania śledzenia

Problem ze śledzeniem nr 18876

Stare zachowanie

Przed wersją EF Core 3.0, można było zapytać posiadane jednostki jak każdą inną nawigację.

context.People.Select(p => p.Address);

Nowe zachowanie

Począwszy od wersji 3.0, EF Core zgłosi wyjątek, jeśli zapytanie śledzące projektuje jednostkę zależną bez właściciela.

Dlaczego

Nie można manipulować należącymi jednostkami bez właściciela, więc w zdecydowanej większości przypadków wykonywanie zapytań względem nich w ten sposób jest błędem.

Środki zaradcze

Jeśli jednostka będąca własnością powinna być modyfikowana w jakikolwiek sposób później, właściciel powinien zostać uwzględniony w zapytaniu.

W przeciwnym razie dodaj wywołanie AsNoTracking() :

context.People.Select(p => p.Address).AsNoTracking();

Właściwości dziedziczone z niemapowanych typów są teraz mapowane na jedną kolumnę dla wszystkich typów pochodnych

Problem ze śledzeniem nr 13998

Stare zachowanie

Rozważ następujący model :

public abstract class EntityBase
{
    public int Id { get; set; }
}

public abstract class OrderBase : EntityBase
{
    public int ShippingAddress { get; set; }
}

public class BulkOrder : OrderBase
{
}

public class Order : OrderBase
{
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OrderBase>();
    modelBuilder.Entity<EntityBase>();
    modelBuilder.Entity<BulkOrder>();
    modelBuilder.Entity<Order>();
}

Przed wersją EF Core 3.0 właściwość ShippingAddress była mapowana na oddzielne kolumny dla BulkOrder i Order domyślnie.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core tworzy tylko jedną kolumnę dla programu ShippingAddress.

Dlaczego

Stare zachowanie było nieoczekiwane.

Środki zaradcze

Właściwość nadal może być jawnie mapowana na oddzielną kolumnę dla typów pochodnych:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OrderBase>();
    modelBuilder.Entity<EntityBase>();
    modelBuilder.Entity<BulkOrder>()
        .Property(o => o.ShippingAddress).HasColumnName("BulkShippingAddress");
    modelBuilder.Entity<Order>()
        .Property(o => o.ShippingAddress).HasColumnName("ShippingAddress");
}

Konwencja dotycząca właściwości klucza obcego nie odpowiada już tej samej nazwie, co właściwość nadrzędna.

Śledzenie problemu nr 13274

Stare zachowanie

Rozważ następujący model :

public class Customer
{
    public int CustomerId { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
}

Przed EF Core 3.0, właściwość CustomerId była używana jako klucz obcy zwyczajowo. Jednak jeśli Order jest typem posiadanym, to również uczyniłoby to CustomerId kluczem podstawowym, co zazwyczaj nie jest oczekiwaniem.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core nie próbuje używać właściwości dla kluczy obcych zgodnie z konwencją, jeśli mają taką samą nazwę jak właściwość główna. Główna nazwa typu połączona z główną nazwą właściwości, a nazwa nawigacji połączona z głównymi wzorcami nazw właściwości są nadal zgodne. Na przykład:

public class Customer
{
    public int Id { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
}
public class Customer
{
    public int Id { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int BuyerId { get; set; }
    public Customer Buyer { get; set; }
}

Dlaczego

Ta zmiana została wprowadzona, aby uniknąć błędnego zdefiniowania właściwości klucza podstawowego dla jednostki typu posiadanego.

Środki zaradcze

Jeśli właściwość miała być kluczem obcym, a tym samym częścią klucza podstawowego, jawnie skonfiguruj ją jako taką.

Połączenie z bazą danych jest teraz zamykane, jeśli nie jest już używane, zanim zakończy się TransactionScope.

Śledzenie zadania nr 14218

Stare zachowanie

Przed EF Core 3.0, jeśli kontekst otwiera połączenie wewnątrz TransactionScope, połączenie pozostaje otwarte, gdy bieżący TransactionScope jest aktywny.

using (new TransactionScope())
{
    using (AdventureWorks context = new AdventureWorks())
    {
        context.ProductCategories.Add(new ProductCategory());
        await context.SaveChangesAsync();

        // Old behavior: Connection is still open at this point

        var categories = await context.ProductCategories().ToListAsync();
    }
}

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core zamyka połączenie natychmiast po zakończeniu korzystania z niego.

Dlaczego

Ta zmiana umożliwia używanie wielu kontekstów w tym samym TransactionScope pliku. Nowe zachowanie jest również zgodne z platformą EF6.

Środki zaradcze

Jeśli połączenie musi pozostać otwarte, to jawne wywołanie OpenConnection() zapewni, że program EF Core nie zamknie go przedwcześnie.

using (new TransactionScope())
{
    using (AdventureWorks context = new AdventureWorks())
    {
        await context.Database.OpenConnectionAsync();
        context.ProductCategories.Add(new ProductCategory());
        await context.SaveChangesAsync();

        var categories = await context.ProductCategories().ToListAsync();
        await context.Database.CloseConnectionAsync();
    }
}

Każda właściwość używa niezależnej generacji klucza całkowitego w pamięci

Śledzenie zgłoszenia nr 6872

Stare zachowanie

Przed programem EF Core 3.0 jeden udostępniony generator wartości był używany dla wszystkich właściwości klucza całkowitego w pamięci.

Nowe zachowanie

Począwszy od wersji EF Core 3.0, każda właściwość klucza całkowitego otrzymuje własny generator wartości podczas korzystania z bazy danych In-Memory. Ponadto jeśli baza danych zostanie usunięta, generowanie klucza zostanie zresetowane dla wszystkich tabel.

Dlaczego

Ta zmiana została wprowadzona w celu dokładniejszego dopasowania generowania klucza w pamięci do rzeczywistego generowania kluczy bazy danych i zwiększenia możliwości odizolowania testów od siebie podczas korzystania z bazy danych w pamięci.

Środki zaradcze

Może to uszkodzić aplikację, która opiera się na określonych wartościach klucza w pamięci, które mają zostać ustawione. Zamiast tego nie należy polegać na określonych wartościach klucza lub aktualizowaniu, aby dopasować je do nowego zachowania.

Pola kopii zapasowej są używane domyślnie

Problem ze śledzeniem nr 12430

Stare zachowanie

Przed 3.0, nawet jeśli pole zapasowe dla właściwości było znane, program EF Core nadal będzie domyślnie odczytywać i zapisywać wartość właściwości przy użyciu metody pobierania właściwości i ustawiania. Wyjątkiem było wykonanie zapytania, w którym pole pomocnicze zostałoby ustawione bezpośrednio, jeśli jego wartość jest znana.

Nowe zachowanie

Począwszy od programu EF Core 3.0, jeśli pole zapasowe właściwości jest znane, program EF Core będzie zawsze odczytywał i zapisywał te właściwości przy użyciu pola zapasowego. Może to spowodować przerwanie działania aplikacji, jeśli aplikacja korzysta z dodatkowego zachowania zakodowanego w metodach getter lub setter.

Dlaczego

Ta zmiana została wprowadzona w celu uniemożliwienia programowi EF Core błędnego wyzwalania logiki biznesowej domyślnie podczas wykonywania operacji bazy danych obejmujących jednostki.

Środki zaradcze

Zachowanie przed 3.0 można przywrócić za pomocą konfiguracji trybu dostępu do właściwości w systemie ModelBuilder. Na przykład:

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);

Zgłaszaj, czy znaleziono wiele zgodnych pól kopii zapasowych

Problem ze śledzeniem nr 12523

Stare zachowanie

Przed programem EF Core 3.0, jeśli wiele pól pasuje do reguł znajdowania pola zapasowego właściwości, jedno pole zostanie wybrane na podstawie pewnej kolejności pierwszeństwa. Może to spowodować, że niewłaściwe pole będzie używane w niejednoznacznych przypadkach.

Nowe zachowanie

Począwszy od programu EF Core 3.0, jeśli wiele pól jest dopasowanych do tej samej właściwości, zgłaszany jest wyjątek.

Dlaczego

Ta zmiana została wprowadzona, aby uniknąć dyskretnego używania jednego pola w innym, gdy tylko jedno pole może być poprawne.

Środki zaradcze

Właściwości z niejednoznacznymi polami zapasowymi muszą mieć wyraźnie określone, które pole ma być używane. Na przykład przy użyciu płynnego interfejsu API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .HasField("_id");

Nazwy właściwości tylko dla pól powinny być zgodne z nazwą pola

Stare zachowanie

Przed programem EF Core 3.0 właściwość może być określona przez wartość ciągu i jeśli nie znaleziono właściwości o tej nazwie na typie platformy .NET, program EF Core spróbuje dopasować ją do pola przy użyciu reguł konwencji.

private class Blog
{
    private int _id;
    public string Name { get; set; }
}
modelBuilder
    .Entity<Blog>()
    .Property("Id");

Nowe zachowanie

Począwszy od EF Core 3.0, właściwość pola musi być dokładnie zgodna z nazwą pola.

modelBuilder
    .Entity<Blog>()
    .Property("_id");

Dlaczego

Ta zmiana została wprowadzona, aby uniknąć używania tego samego pola dla dwóch właściwości o podobnej nazwie. Powoduje to również, że zgodne reguły właściwości tylko dla pól są takie same jak właściwości mapowane na właściwości CLR.

Środki zaradcze

Właściwości tylko pola muszą mieć taką samą nazwę jak pole, do którego są mapowane. W przyszłej wersji programu EF Core po wersji 3.0 planujemy ponowne włączenie jawnego konfigurowania nazwy pola, która różni się od nazwy właściwości (zobacz problem nr 15307):

modelBuilder
    .Entity<Blog>()
    .Property("Id")
    .HasField("_id");

AddDbContext/AddDbContextPool nie wywołuje już funkcji AddLogging i AddMemoryCache

Problem ze śledzeniem nr 14756

Stare zachowanie

Przed EF Core 3.0, wywołanie AddDbContext lub AddDbContextPool rejestrowało również usługi logowania i buforowania pamięci w DI za pomocą wywołań AddLogging i AddMemoryCache.

Nowe zachowanie

Od wersji EF Core 3.0, AddDbContext oraz AddDbContextPool nie będą już rejestrować tych usług poprzez wstrzykiwanie zależności (DI).

Dlaczego

Program EF Core 3.0 nie wymaga, aby te usługi były w kontenerze DI aplikacji. Jeśli ILoggerFactory jednak jest zarejestrowany w kontenerze di aplikacji, będzie on nadal używany przez program EF Core.

Środki zaradcze

Jeśli aplikacja potrzebuje tych usług, zarejestruj je jawnie w kontenerze DI przy użyciu polecenia AddLogging lub AddMemoryCache.

AddEntityFramework* dodaje funkcję IMemoryCache z limitem rozmiaru

Zadanie śledzenia nr 12905

Stare zachowanie

Przed EF Core 3.0 wywołanie metod AddEntityFramework* również rejestrowałoby usługi buforowania pamięci z DI bez ograniczenia rozmiaru.

Nowe zachowanie

Począwszy od programu EF Core 3.0, AddEntityFramework* zarejestruje usługę IMemoryCache z limitem rozmiaru. Jeśli inne usługi dodane później zależą od usługi IMemoryCache, mogą szybko osiągnąć domyślny limit powodujący wyjątki lub obniżoną wydajność.

Dlaczego

Użycie usługi IMemoryCache bez limitu może spowodować niekontrolowane użycie pamięci, jeśli w logice buforowania zapytań występuje usterka lub zapytania są generowane dynamicznie. Posiadanie domyślnego limitu ogranicza potencjalny atak DoS.

Środki zaradcze

W większości przypadków wywoływanie AddEntityFramework* nie jest konieczne, jeśli wywoływana jest również AddDbContext lub AddDbContextPool. W związku z tym najlepszym środkiem zaradczym jest usunięcie wywołania AddEntityFramework*.

Jeśli aplikacja wymaga tych usług, zarejestruj implementację IMemoryCache jawnie z kontenerem DI wcześniej przy użyciu funkcji AddMemoryCache.

Funkcja DbContext.Entry wykonuje teraz lokalną funkcję DetectChanges

Problem ze śledzeniem nr 13552

Stare zachowanie

Przed EF Core 3.0, wywołanie DbContext.Entry powodowało wykrywanie zmian dla wszystkich śledzonych encji. Dzięki temu stan uwidoczniony w obiekcie EntityEntry był aktualny.

Nowe zachowanie

Począwszy od EF Core 3.0, wywołanie DbContext.Entry spowoduje teraz tylko próbę wykrycia zmian w danej encji i wszelkich śledzonych powiązanych encji głównych. Oznacza to, że zmiany w innym miejscu mogły nie zostać wykryte przez wywołanie tej metody, co może mieć wpływ na stan aplikacji.

Należy pamiętać, że jeśli ChangeTracker.AutoDetectChangesEnabled jest ustawione na false, nawet to lokalne wykrywanie zmian zostanie wyłączone.

Inne metody, które powodują wykrywanie zmian — na przykład ChangeTracker.Entries i SaveChanges— nadal powodują pełne DetectChanges wszystkich śledzonych encji.

Dlaczego

Ta zmiana została wprowadzona w celu zwiększenia domyślnej wydajności korzystania z programu context.Entry.

Środki zaradcze

Wywołaj ChangeTracker.DetectChanges() jawnie przed wywołaniem Entry, aby zagwarantować zachowanie sprzed wersji 3.0.

Klucze ciągów i tablic bajtów nie są domyślnie generowane przez klienta

Zagadnienie śledzenia nr 14617

Stare zachowanie

Przed EF Core 3.0 właściwości string i byte[] mogły być używane bez jawnego ustawiania wartości innej niż null. W takim przypadku wartość klucza zostanie wygenerowana na kliencie jako identyfikator GUID, serializowany do bajtów dla elementu byte[].

Nowe zachowanie

Począwszy od EF Core 3.0, zgłaszany będzie wyjątek wskazujący, że nie ustawiono wartości klucza.

Dlaczego

Ta zmiana została wprowadzona, ponieważ wartości generowane string/byte[] przez klienta zazwyczaj nie są przydatne, a domyślne zachowanie utrudniało wnioskowanie o wygenerowanych wartościach kluczy w typowy sposób.

Środki zaradcze

Zachowanie przed 3.0 można uzyskać przez jawne określenie, że właściwości klucza powinny używać wygenerowanych wartości, jeśli nie ustawiono żadnej innej wartości innej niż null. Na przykład za pomocą płynnego interfejsu API:

modelBuilder
    .Entity<Blog>()
    .Property(e => e.Id)
    .ValueGeneratedOnAdd();

Lub z adnotacjami danych:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }

ILoggerFactory jest teraz usługą o określonym zakresie

Problem ze śledzeniem nr 14698

Stare zachowanie

Przed programem EF Core 3.0 ILoggerFactory została zarejestrowana jako pojedyncza usługa.

Nowe zachowanie

Począwszy od programu EF Core 3.0, ILoggerFactory jest teraz zarejestrowany jako zakres.

Dlaczego

Ta zmiana została wprowadzona w celu umożliwienia skojarzenia rejestratora z wystąpieniem DbContext, które umożliwia używanie innych funkcji i eliminuje niektóre przypadki patologii, takie jak nagły wzrost liczby wewnętrznych dostawców usług.

Środki zaradcze

Ta zmiana nie powinna mieć wpływu na kod aplikacji, chyba że rejestruje i korzysta z usług niestandardowych u wewnętrznego dostawcy usług EF Core. To nie jest typowe. W takich przypadkach większość rzeczy będzie nadal działać, ale każda pojedyncza usługa, która była zależna od ILoggerFactory , musi zostać zmieniona, aby uzyskać element ILoggerFactory w inny sposób.

Jeśli wystąpią takie sytuacje, zgłoś problem w systemie śledzenia problemów EF Core na GitHub, aby poinformować nas, w jaki sposób używasz ILoggerFactory tak, abyśmy mogli lepiej zrozumieć, jak w przyszłości tego już nie przerywać.

Obiekty proxy leniwego ładowania nie zakładają już, że właściwości nawigacji są całkowicie załadowane.

Problem ze śledzeniem nr 12780

Stare zachowanie

Przed EF Core 3.0, gdy DbContext został usunięty, nie było sposobu, aby dowiedzieć się, czy dana właściwość nawigacyjna encji pobranej z tego kontekstu została w pełni załadowana, czy nie. Zamiast tego serwery proxy zakładają, że nawigacja referencyjna jest ładowana, jeśli ma wartość inną niż null, i że nawigacja kolekcji jest ładowana, jeśli nie jest pusta. W takich przypadkach próba leniwego ładowania byłaby operacją bez efektu.

Nowe zachowanie

Począwszy od EF Core 3.0, proxy śledzą, czy właściwość nawigacyjna jest załadowana. Oznacza to, że próba uzyskania dostępu do właściwości nawigacji ładowanej po usunięciu kontekstu zawsze będzie bezoperacyjna, nawet jeśli załadowana nawigacja jest pusta lub ma wartość null. Z drugiej strony próba uzyskania dostępu do właściwości nawigacji, która nie jest załadowana, zgłosi wyjątek, jeśli kontekst zostanie usunięty, nawet jeśli właściwość nawigacji jest niepustą kolekcją. Jeśli wystąpi taka sytuacja, oznacza to, że kod aplikacji próbuje użyć ładowania leniwego w nieprawidłowym czasie, a aplikacja powinna zostać zmieniona, aby tego nie robić.

Dlaczego

Ta zmiana została wprowadzona, aby zachowanie było spójne i poprawne podczas próby opóźnionego ładowania w usuniętym DbContext wystąpieniu.

Środki zaradcze

Zaktualizuj kod aplikacji, aby nie próbował leniwie ładować z usuniętym kontekstem lub skonfiguruj ją tak, aby była operacją nieefektywną, zgodnie z opisem w komunikacie o wyjątku.

Nadmierne tworzenie wewnętrznych dostawców usług jest teraz domyślnie błędem

Problem ze śledzeniem nr 10236

Stare zachowanie

Przed programem EF Core 3.0 zostanie zarejestrowane ostrzeżenie dla aplikacji tworzącej patologiczną liczbę dostawców usług wewnętrznych.

Nowe zachowanie

Począwszy od programu EF Core 3.0, to ostrzeżenie jest teraz uznawane za błąd i zgłaszany jest wyjątek.

Dlaczego

Ta zmiana została wprowadzona w celu polepszenia jakości kodu aplikacji poprzez bardziej wyraźne ujawnienie tego patologicznego przypadku.

Środki zaradcze

Najbardziej odpowiednią przyczyną działania w przypadku napotkania tego błędu jest zrozumienie głównej przyczyny i zaprzestanie tworzenia tak wielu wewnętrznych dostawców usług. Jednak błąd można przekonwertować z powrotem na ostrzeżenie (lub można zignorować) za pomocą konfiguracji w DbContextOptionsBuilder. Na przykład:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .ConfigureWarnings(w => w.Log(CoreEventId.ManyServiceProvidersCreatedWarning));
}

Nowe zachowanie dla funkcji HasOne/HasMany wywoływanych z pojedynczym argumentem typu string.

Śledzenie zgłoszenia nr 9171

Stare zachowanie

Przed EF Core 3.0, wywołanie HasOne lub HasMany z jednym ciągiem znaków było interpretowane w mylący sposób. Na przykład:

modelBuilder.Entity<Samurai>().HasOne("Entrance").WithOne();

Kod wygląda tak, jakby odnosił Samurai do innego typu jednostki, używając właściwości nawigacyjnej Entrance, która może być prywatna.

W rzeczywistości ten kod próbuje utworzyć relację z typem jednostki o nazwie Entrance bez właściwości nawigacji.

Nowe zachowanie

Począwszy od wersji EF Core 3.0, powyższy kod wykonuje teraz to, co wcześniej wydawało się, że powinien był robić.

Dlaczego

Stare zachowanie było bardzo mylące, zwłaszcza podczas odczytywania kodu konfiguracji i wyszukiwania błędów.

Środki zaradcze

Spowoduje to przerwanie tylko aplikacji, które jawnie konfigurują relacje przy użyciu ciągów dla nazw typów i bez jawnego określenia właściwości nawigacji. Nie jest to powszechne. Poprzednie zachowanie można uzyskać poprzez jawne przekazanie nazwy właściwości nawigacji null. Na przykład:

modelBuilder.Entity<Samurai>().HasOne("Some.Entity.Type.Name", null).WithOne();

Typ zwracany dla kilku metod asynchronicznych został zmieniony z Task na ValueTask

Śledzenie problemu nr 15184

Stare zachowanie

Następujące metody asynchroniczne wcześniej zwracały Task<T>:

  • DbContext.FindAsync()
  • DbSet.FindAsync()
  • DbContext.AddAsync()
  • DbSet.AddAsync()
  • ValueGenerator.NextValueAsync() (i klasy wyprowadzające)

Nowe zachowanie

Wyżej wymienione metody teraz zwracają ValueTask<T> w taki sam T sposób jak poprzednio.

Dlaczego

Ta zmiana zmniejsza liczbę alokacji sterty zachodzącej podczas wywoływania tych metod, poprawiając ogólną wydajność.

Środki zaradcze

Aplikacje oczekujące tylko na powyższe interfejsy API muszą zostać ponownie skompilowane — żadne zmiany źródła nie są konieczne. Bardziej złożone użycie (np. przekazanie zwróconego elementu Task do Task.WhenAny()) zwykle wymaga przekonwertowania zwróconego ValueTask<T> na Task<T> przez wywołanie metody AsTask(). Należy pamiętać, że spowoduje to negację redukcji alokacji, którą wprowadza ta zmiana.

Adnotacja Relational:TypeMapping jest teraz po prostu TypeMapping

Problem ze śledzeniem nr 9913

Stare zachowanie

Nazwa dla adnotacji mapowania typów to "Relational:TypeMapping".

Nowe zachowanie

Nazwa dla adnotacji mapowania typów to teraz "TypeMapping".

Dlaczego

Mapowania typów są teraz używane dla nie tylko dostawców relacyjnych baz danych.

Środki zaradcze

Spowoduje to przerwanie tylko tych aplikacji, które uzyskują dostęp do mapowania typów bezpośrednio za pomocą adnotacji, co jest rzadko spotykane. Najbardziej odpowiednim działaniem naprawczym jest użycie interfejsu API do uzyskiwania dostępu do mapowań typów zamiast bezpośredniego używania adnotacji.

ToTable w przypadku typu pochodnego zgłasza wyjątek

Problem ze śledzeniem nr 11811

Stare zachowanie

Przed wersją EF Core 3.0, wywołanie na typie pochodnym było ignorowane, ponieważ jedyną stosowaną strategią mapowania dziedziczenia była TPH, gdzie nie jest to prawidłowe. ToTable()

Nowe zachowanie

Począwszy od programu EF Core 3.0 i w ramach przygotowań do dodawania obsługi TPT i TPC w nowszej wersji, wywołany typ pochodny zgłosi teraz wyjątek, ToTable() aby uniknąć nieoczekiwanej zmiany mapowania w przyszłości.

Dlaczego

Obecnie nie można mapować typu pochodnego na inną tabelę. Ta zmiana pozwala uniknąć przerwania w przyszłości, gdy stanie się prawidłową rzeczą do zrobienia.

Środki zaradcze

Usuń wszelkie próby mapowania typów pochodnych na inne tabele.

ForSqlServerHasIndex został zastąpiony HasIndex

Problem ze śledzeniem nr 12366

Stare zachowanie

Przed EF Core 3.0 ForSqlServerHasIndex().ForSqlServerInclude() udostępniał sposób konfigurowania kolumn używanych z INCLUDE.

Nowe zachowanie

Od EF Core 3.0, użycie Include na indeksie jest teraz obsługiwane na poziomie relacyjnym. Użyj HasIndex().ForSqlServerInclude().

Dlaczego

Ta zmiana została wprowadzona w celu skonsolidowania interfejsu API dla indeksów z Include w jedno miejsce dla wszystkich dostawców baz danych.

Środki zaradcze

Użyj nowego interfejsu API, jak pokazano powyżej.

Zmiany interfejsu API metadanych

Sprawa śledzenia nr 214

Nowe zachowanie

Następujące właściwości zostały przekonwertowane na metody rozszerzenia:

  • IEntityType.QueryFilter —>GetQueryFilter()
  • IEntityType.DefiningQuery —>GetDefiningQuery()
  • IProperty.IsShadowProperty —>IsShadowProperty()
  • IProperty.BeforeSaveBehavior —>GetBeforeSaveBehavior()
  • IProperty.AfterSaveBehavior —>GetAfterSaveBehavior()

Dlaczego

Ta zmiana upraszcza implementację wyżej wymienionych interfejsów.

Środki zaradcze

Użyj nowych metod rozszerzenia.

Zmiany interfejsu API metadanych specyficzne dla dostawcy

Sprawa śledzenia nr 214

Nowe zachowanie

Metody rozszerzeń specyficznych dla dostawcy zostaną uproszczone:

  • IProperty.Relational().ColumnName —>IProperty.GetColumnName()
  • IEntityType.SqlServer().IsMemoryOptimized —>IEntityType.IsMemoryOptimized()
  • PropertyBuilder.UseSqlServerIdentityColumn() —>PropertyBuilder.UseIdentityColumn()

Dlaczego

Ta zmiana upraszcza implementację wyżej wymienionych metod rozszerzeń.

Środki zaradcze

Użyj nowych metod rozszerzenia.

Program EF Core nie wysyła już pragma dla wymuszania klucza FK SQLite

Problem ze śledzeniem nr 12151

Stare zachowanie

Przed programem EF Core 3.0 program EF Core będzie wysyłał PRAGMA foreign_keys = 1 po otwarciu połączenia z sqlite.

Nowe zachowanie

Od EF Core 3.0, EF Core nie wysyła już PRAGMA foreign_keys = 1 po otwarciu połączenia z SQLite.

Dlaczego

Ta zmiana została wprowadzona, ponieważ program EF Core używa SQLitePCLRaw.bundle_e_sqlite3 domyślnie, co z kolei oznacza, że wymuszanie szyfrowania FK jest domyślnie włączone i nie musi być jawnie włączone za każdym razem, gdy połączenie jest otwarte.

Środki zaradcze

Klucze obce są domyślnie włączone w SQLitePCLRaw.bundle_e_sqlite3, która jest domyślnie używana dla platformy EF Core. W innych przypadkach klucze obce można włączyć, określając Foreign Keys=True w parametry połączenia.

Microsoft.EntityFrameworkCore.Sqlite jest teraz zależny od SQLitePCLRaw.bundle_e_sqlite3

Stare zachowanie

Przed programem EF Core 3.0 używany był program SQLitePCLRaw.bundle_greenEF Core.

Nowe zachowanie

Począwszy od EF Core 3.0, EF Core używa SQLitePCLRaw.bundle_e_sqlite3.

Dlaczego

Ta zmiana została wprowadzona tak, aby wersja sqLite używana w systemie iOS była zgodna z innymi platformami.

Środki zaradcze

Aby użyć natywnej wersji SQLite w systemie iOS, skonfiguruj opcję Microsoft.Data.Sqlite korzystania z innego SQLitePCLRaw pakietu.

Wartości guid są teraz przechowywane jako TEKST w sqlite

Kwestia śledzenia nr 15078

Stare zachowanie

Wartości identyfikatora GUID były wcześniej przechowywane jako wartości obiektów BLOB w SQLite.

Nowe zachowanie

Wartości identyfikatora GUID są teraz przechowywane jako TEXT.

Dlaczego

Binarny format identyfikatorów GUID nie jest ustandaryzowany. Przechowywanie wartości w formacie TEXT sprawia, że baza danych jest bardziej zgodna z innymi technologiami.

Środki zaradcze

Istniejące bazy danych można migrować do nowego formatu, wykonując polecenie SQL w następujący sposób.

UPDATE MyTable
SET GuidColumn = hex(substr(GuidColumn, 4, 1)) ||
                 hex(substr(GuidColumn, 3, 1)) ||
                 hex(substr(GuidColumn, 2, 1)) ||
                 hex(substr(GuidColumn, 1, 1)) || '-' ||
                 hex(substr(GuidColumn, 6, 1)) ||
                 hex(substr(GuidColumn, 5, 1)) || '-' ||
                 hex(substr(GuidColumn, 8, 1)) ||
                 hex(substr(GuidColumn, 7, 1)) || '-' ||
                 hex(substr(GuidColumn, 9, 2)) || '-' ||
                 hex(substr(GuidColumn, 11, 6))
WHERE typeof(GuidColumn) == 'blob';

W programie EF Core można również kontynuować korzystanie z poprzedniego zachowania, konfigurując konwerter wartości dla tych właściwości.

modelBuilder
    .Entity<MyEntity>()
    .Property(e => e.GuidProperty)
    .HasConversion(
        g => g.ToByteArray(),
        b => new Guid(b));

Microsoft.Data.Sqlite może odczytywać wartości GUID zarówno z kolumn BLOB, jak i TEXT; jednakże, ponieważ domyślny format parametrów i stałych uległ zmianie, prawdopodobnie będzie konieczne podjęcie działań w większości scenariuszy z GUID.

Wartości znaków są teraz przechowywane jako TEKST w sqlite

Problem ze śledzeniem nr 15020

Stare zachowanie

Wartości char były wcześniej przechowywane jako wartości INTEGER w sqlite. Na przykład wartość char A została zapisana jako wartość całkowita 65.

Nowe zachowanie

Wartości znaków są teraz przechowywane jako TEKST.

Dlaczego

Przechowywanie wartości jako tekstu jest bardziej naturalne i sprawia, że baza danych jest bardziej zgodna z innymi technologiami.

Środki zaradcze

Istniejące bazy danych można migrować do nowego formatu, wykonując polecenie SQL w następujący sposób.

UPDATE MyTable
SET CharColumn = char(CharColumn)
WHERE typeof(CharColumn) = 'integer';

W programie EF Core można również kontynuować korzystanie z poprzedniego zachowania, konfigurując konwerter wartości dla tych właściwości.

modelBuilder
    .Entity<MyEntity>()
    .Property(e => e.CharProperty)
    .HasConversion(
        c => (long)c,
        i => (char)i);

Microsoft.Data.Sqlite może również odczytywać wartości znaków zarówno z kolumn INTEGER, jak i TEXT, więc niektóre scenariusze mogą nie wymagać żadnej akcji.

Identyfikatory migracji są teraz generowane przy użyciu niezmiennego kalendarza kultury

Zadanie śledzenia nr 12978

Stare zachowanie

Identyfikatory migracji zostały przypadkowo wygenerowane przy użyciu kalendarza bieżącej kultury.

Nowe zachowanie

Identyfikatory migracji są teraz zawsze generowane przy użyciu niezmiennego kalendarza kultury (Gregorian).

Dlaczego

Kolejność migracji jest ważna podczas aktualizowania bazy danych lub rozwiązywania konfliktów scalania. Użycie niezmiennego kalendarza pozwala uniknąć problemów z porządkowaniami, które mogą wynikać z tego, że członkowie zespołu mają różne kalendarze systemowe.

Środki zaradcze

Ta zmiana dotyczy każdego, kto korzysta z kalendarza innego niż gregoriański, w którym rok jest większy niż kalendarz gregoriański (taki jak tajski kalendarz buddyjski). Istniejące identyfikatory migracji należy zaktualizować, aby nowe migracje były uporządkowane po istniejących migracjach.

Identyfikator migracji można znaleźć w atrybucie Migracja w plikach projektanta migracji.

 [DbContext(typeof(MyDbContext))]
-[Migration("25620318122820_MyMigration")]
+[Migration("20190318122820_MyMigration")]
 partial class MyMigration
 {

Należy również zaktualizować tabelę Historii migracji.

UPDATE __EFMigrationsHistory
SET MigrationId = CONCAT(LEFT(MigrationId, 4)  - 543, SUBSTRING(MigrationId, 4, 150))

Polecenie UseRowNumberForPaging zostało usunięte

Problem ze śledzeniem nr 16400

Stare zachowanie

Przed programem EF Core 3.0 UseRowNumberForPaging można użyć do wygenerowania bazy danych SQL na potrzeby stronicowania zgodnego z programem SQL Server 2008.

Nowe zachowanie

Począwszy od programu EF Core 3.0, program EF wygeneruje tylko program SQL na potrzeby stronicowania, który jest zgodny tylko z nowszymi wersjami programu SQL Server.

Dlaczego

Wprowadzamy tę zmianę, ponieważ program SQL Server 2008 nie jest już obsługiwanym produktem i aktualizacja tej funkcji w celu pracy ze zmianami zapytań wprowadzonych w programie EF Core 3.0 jest znacząca.

Środki zaradcze

Zalecamy zaktualizowanie do nowszej wersji programu SQL Server lub użycie wyższego poziomu zgodności, aby wygenerowany program SQL był obsługiwany. Oznacza to, że jeśli nie możesz tego zrobić, skomentuj problem ze śledzeniem ze szczegółami. Możemy ponownie podjąć tę decyzję na podstawie opinii.

Informacje/metadane rozszerzenia zostały usunięte z rozszerzenia IDbContextOptionsExtension

Problem ze śledzeniem nr 16119

Stare zachowanie

IDbContextOptionsExtension zawarte metody, które dostarczają metadanych dotyczących rozszerzenia.

Nowe zachowanie

Metody te zostały przeniesione do nowej DbContextOptionsExtensionInfo abstrakcyjnej klasy bazowej, która jest zwracana z nowej IDbContextOptionsExtension.Info właściwości.

Dlaczego

W wersjach z wersji 2.0 do 3.0 musieliśmy kilka razy dodać lub zmienić te metody. Podzielenie ich na nową abstrakcyjną klasę bazową ułatwi wprowadzanie tych zmian bez przerywania istniejących rozszerzeń.

Środki zaradcze

Zaktualizuj rozszerzenia, aby postępować zgodnie z nowym wzorcem. Przykłady można znaleźć w wielu implementacjach IDbContextOptionsExtension dla różnych rodzajów rozszerzeń w kodzie źródłowym platformy EF Core.

Element LogQueryPossibleExceptionWithAggregateOperator został przemianowany

Śledzenie zgłoszenia #10985

Zmień

RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator zmieniono nazwę na RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning.

Dlaczego

Wyrównuje nazewnictwo tego zdarzenia ostrzegawczego ze wszystkimi innymi zdarzeniami ostrzegawczymi.

Środki zaradcze

Użyj nowej nazwy. (Należy pamiętać, że numer identyfikatora zdarzenia nie został zmieniony).

Wyjaśnienie interfejsu API dla nazw ograniczeń klucza obcego

Problem ze śledzeniem nr 10730

Stare zachowanie

Przed programem EF Core 3.0 nazwy ograniczeń klucza obcego były nazywane po prostu "nazwą". Na przykład:

var constraintName = myForeignKey.Name;

Nowe zachowanie

Począwszy od programu EF Core 3.0, nazwy ograniczeń klucza obcego są teraz określane jako "nazwa ograniczenia". Na przykład:

var constraintName = myForeignKey.ConstraintName;

Dlaczego

Ta zmiana zapewnia spójność nazewnictwa w tym obszarze, a także wyjaśnia, że jest to nazwa ograniczenia klucza obcego, a nie nazwa kolumny lub właściwości zdefiniowanej przez klucz obcy.

Środki zaradcze

Użyj nowej nazwy.

IRelationalDatabaseCreator.HasTables/HasTablesAsync zostały upublicznione

Zagadnienie do śledzenia nr 15997

Stare zachowanie

Przed programem EF Core 3.0 te metody były chronione.

Nowe zachowanie

Począwszy od programu EF Core 3.0, te metody są publiczne.

Dlaczego

Te metody są używane przez program EF do określenia, czy baza danych jest tworzona, ale pusta. Może to być również przydatne z zewnątrz EF przy określaniu, czy zastosować migracje.

Środki zaradcze

Zmień dostępność wszelkich przesłonięć.

Microsoft.EntityFrameworkCore.Design jest teraz pakietem DevelopmentDependency

Problem ze śledzeniem nr 11506

Stare zachowanie

Przed wersją EF Core 3.0 Microsoft.EntityFrameworkCore.Design był zwykłym pakietem NuGet, którego zestaw mógł być przywoływany przez projekty, które były od niego zależne.

Nowe zachowanie

Począwszy od programu EF Core 3.0, jest to pakiet DevelopmentDependency. Oznacza to, że zależność nie będzie przepływać przechodnio do innych projektów i że domyślnie nie można odwoływać się do jej zestawu.

Dlaczego

Ten pakiet ma być używany tylko w czasie projektowania. Wdrożone aplikacje nie powinny się do niego odwoływać. Ustawienie pakietu jako DevelopmentDependency wzmacnia tę rekomendację.

Środki zaradcze

Jeśli chcesz odwołać się do tego pakietu, aby zmienić zachowanie EF Core w czasie projektowania, możesz zaktualizować metadane elementu PackageReference w projekcie.

<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
  <PrivateAssets>all</PrivateAssets>
  <!-- Remove IncludeAssets to allow compiling against the assembly -->
  <!--<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
</PackageReference>

Jeśli pakiet jest przywoływany przechodnio za pośrednictwem narzędzia Microsoft.EntityFrameworkCore.Tools, należy dodać jawny element PackageReference do pakietu, aby zmienić jego metadane. Takie jawne odwołanie należy dodać do dowolnego projektu, w którym potrzebne są typy z pakietu.

SQLitePCL.raw zaktualizowano do wersji 2.0.0

Problem ze śledzeniem nr 14824

Stare zachowanie

Microsoft.EntityFrameworkCore.Sqlite wcześniej zależało od wersji 1.1.12 SQLitePCL.raw.

Nowe zachowanie

Zaktualizowaliśmy nasz pakiet tak, aby był zależny od wersji 2.0.0.

Dlaczego

Wersja 2.0.0 SQLitePCL.raw jest przeznaczona dla platformy .NET Standard 2.0. Wcześniej była przeznaczona dla platformy .NET Standard 1.1, która wymagała obszernego zamknięcia pakietów zależnych, aby działać poprawnie.

Środki zaradcze

SQLitePCL.raw w wersji 2.0.0 zawiera pewne zmiany łamiące zgodność. Zapoznaj się z notatkami o wydaniu, aby uzyskać szczegółowe informacje.

NetTopologySuite zaktualizowano do wersji 2.0.0

Problem ze śledzeniem nr 14825

Stare zachowanie

Pakiety przestrzenne były wcześniej zależne od wersji 1.15.1 aplikacji NetTopologySuite.

Nowe zachowanie

Zaktualizowaliśmy nasz pakiet, aby był zależny od wersji 2.0.0.

Dlaczego

Wersja 2.0.0 aplikacji NetTopologySuite ma na celu rozwiązanie kilku problemów z użytecznością napotykanych przez użytkowników platformy EF Core.

Środki zaradcze

NetTopologySuite w wersji 2.0.0 zawiera pewne zmiany powodujące niezgodność. Zobacz uwagi do wydania aby uzyskać szczegółowe informacje.

Element Microsoft.Data.SqlClient jest używany zamiast Elementu System.Data.SqlClient

Zadanie śledzenia nr 15636

Stare zachowanie

Microsoft.EntityFrameworkCore.SqlServer wcześniej było zależne od System.Data.SqlClient.

Nowe zachowanie

Zaktualizowaliśmy nasz pakiet, aby zależeć od elementu Microsoft.Data.SqlClient.

Dlaczego

Microsoft.Data.SqlClient jest flagowym sterownikiem dostępu do danych dla programu SQL Server w przyszłości, a program System.Data.SqlClient nie jest już przedmiotem programowania. Niektóre ważne funkcje, takie jak Always Encrypted, są dostępne tylko w programie Microsoft.Data.SqlClient.

Środki zaradcze

Jeśli kod przyjmuje bezpośrednią zależność od elementu System.Data.SqlClient, należy zmienić go tak, aby odwołył się do elementu Microsoft.Data.SqlClient; ponieważ te dwa pakiety zachowują bardzo wysoki stopień zgodności interfejsu API, powinno to być tylko prosta zmiana pakietu i przestrzeni nazw.

Należy skonfigurować wiele niejednoznacznych relacji odwołujących się do siebie

Problem ze śledzeniem nr 13573

Stare zachowanie

Typ jednostki z wieloma własnymi odwołaniami do właściwości nawigacji jednokierunkowej i dopasowywania zestawów FKs został niepoprawnie skonfigurowany jako pojedyncza relacja. Na przykład:

public class User
{
        public Guid Id { get; set; }
        public User CreatedBy { get; set; }
        public User UpdatedBy { get; set; }
        public Guid CreatedById { get; set; }
        public Guid? UpdatedById { get; set; }
}

Nowe zachowanie

Ten scenariusz jest teraz wykrywany w kompilowaniu modelu i zgłaszany jest wyjątek wskazujący, że model jest niejednoznaczny.

Dlaczego

Wynikowy model był niejednoznaczny i prawdopodobnie będzie prawdopodobnie nieprawidłowy w tym przypadku.

Środki zaradcze

Użyj pełnej konfiguracji relacji. Na przykład:

modelBuilder
     .Entity<User>()
     .HasOne(e => e.CreatedBy)
     .WithMany();

 modelBuilder
     .Entity<User>()
     .HasOne(e => e.UpdatedBy)
     .WithMany();

DbFunction.Schema mający wartość null lub będący pustym ciągiem znaków jest ustawiany na domyślny schemat modelu.

Problem ze śledzeniem nr 12757

Stare zachowanie

Funkcja DbFunction skonfigurowana ze schematem jako pusty ciąg była traktowana jako funkcja wbudowana bez schematu. Na przykład poniższy kod zamapuje DatePart funkcję CLR na DATEPART wbudowaną funkcję na serwerze SqlServer.

[DbFunction("DATEPART", Schema = "")]
public static int? DatePart(string datePartArg, DateTime? date) => throw new Exception();

Nowe zachowanie

Wszystkie mapowania DbFunction są uważane za mapowane na funkcje zdefiniowane przez użytkownika. W związku z tym pusta wartość ciągu spowoduje umieszczenie funkcji wewnątrz domyślnego schematu modelu. Może to być schemat skonfigurowany jawnie za pośrednictwem płynnego interfejsu API modelBuilder.HasDefaultSchema() lub dbo w inny sposób.

Dlaczego

Wcześniej pusty schemat był używany jako sposób traktowania funkcji jako wbudowanej, ale ta logika ma zastosowanie tylko w systemie SQL Server, gdzie wbudowane funkcje nie należą do żadnego schematu.

Środki zaradcze

Ręczne konfigurowanie tłumaczenia dbFunction w celu zamapowania go na wbudowaną funkcję.

modelBuilder
    .HasDbFunction(typeof(MyContext).GetMethod(nameof(MyContext.DatePart)))
    .HasTranslation(args => SqlFunctionExpression.Create("DatePart", args, typeof(int?), null));

Program EF Core 3.0 jest przeznaczony dla platformy .NET Standard 2.1, a nie .NET Standard 2.0 Przywrócono

Śledzenie zgłoszenia nr 15498

EF Core 3.0 jest przeznaczony dla .NET Standard 2.1, co stanowi istotną zmianę, wykluczającą aplikacje .NET Framework. Program EF Core 3.1 przywrócił ten element i ponownie jest przeznaczony dla platformy .NET Standard 2.0.

Wykonywanie zapytania jest rejestrowane na poziomie debugowania. Przywrócono.

Śledzenie problemu nr 14523

Przywróciliśmy tę zmianę, ponieważ nowa konfiguracja w programie EF Core 3.0 umożliwia określenie przez aplikację poziomu dziennika dla dowolnego zdarzenia. Aby na przykład przełączyć rejestrowanie SQL na Debug, skonfiguruj jawnie poziom w OnConfiguring lub AddDbContext.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(connectionString)
        .ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Debug)));