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. Zmiany, które spodziewamy się mieć wpływ tylko na dostawców baz danych, są udokumentowane w obszarze zmiany dostawcy.

Podsumowanie

Zmiana powodująca niezgodność Wpływ
Zapytania LINQ nie są już oceniane na kliencie Wysoka
Narzędzie wiersza polecenia platformy EF Core dotnet ef nie jest już częścią zestawu .NET Core SDK Wysoka
DetectChanges honoruje wartości kluczy generowanych przez magazyn Wysoka
Zmieniono nazwy z baz danychSql, ExecuteSql i ExecuteSqlAsync Wysoka
Typy zapytań są konsolidowane przy użyciu typów jednostek Wysoka
Platforma Entity Framework Core nie jest już częścią platformy udostępnionej ASP.NET Core Średnie
Usunięcia kaskadowe są teraz wykonywane natychmiast domyślnie Średnie
Trwa ładowanie powiązanych jednostek w jednym zapytaniu Średnie
Funkcja DeleteBehavior.Restrict ma semantykę czystszą Średnie
Zmieniono interfejs API konfiguracji dla relacji typu należącego do użytkownika Średnie
Każda właściwość używa niezależnej generacji klucza całkowitego w pamięci Średnie
Zapytania śledzenia nie wykonują już rozpoznawania tożsamości Średnie
Zmiany interfejsu API metadanych Średnie
Zmiany interfejsu API metadanych specyficzne dla dostawcy Średnie
Polecenie UseRowNumberForPaging zostało usunięte Średnie
Metoda FromSql, jeśli jest używana z procedurą składowaną, nie może składać się Średnie
Metody FromSql można określić tylko dla katalogów głównych zapytań Niska
Tymczasowe wartości klucza nie są już ustawiane na wystąpienia jednostek Niska
Jednostki zależne współdzielące tabelę z podmiotem zabezpieczeń są teraz opcjonalne Niska
Wszystkie jednostki udostępniające tabelę z kolumną tokenu współbieżności muszą mapować ją na właściwość Niska
Nie można wykonywać zapytań dotyczących jednostek należących do właściciela bez użycia zapytania śledzenia Niska
Właściwości dziedziczone z niemapowanych typów są teraz mapowane na jedną kolumnę dla wszystkich typów pochodnych Niska
Konwencja właściwości klucza obcego nie jest już zgodna z tą samą nazwą co właściwość główna Niska
Połączenie z bazą danych jest teraz zamykane, jeśli nie jest już używane przed ukończeniem transakcjiScope Niska
Pola kopii zapasowej są używane domyślnie Niska
Zgłaszaj, czy znaleziono wiele zgodnych pól kopii zapasowych Niska
Nazwy właściwości tylko dla pól powinny być zgodne z nazwą pola Niska
AddDbContext/AddDbContextPool nie wywołuje już funkcji AddLogging i AddMemoryCache Niska
AddEntityFramework* dodaje funkcję IMemoryCache z limitem rozmiaru Niska
Funkcja DbContext.Entry wykonuje teraz lokalną funkcję DetectChanges Niska
Klucze ciągów i tablic bajtów nie są domyślnie generowane przez klienta Niska
ILoggerFactory jest teraz usługą o określonym zakresie Niska
Serwery proxy ładowania z opóźnieniem nie zakładają już, że właściwości nawigacji są w pełni ładowane Niska
Nadmierne tworzenie wewnętrznych dostawców usług jest teraz domyślnie błędem Niska
Nowe zachowanie funkcji HasOne/HasMany o nazwie z jednym ciągiem Niska
Typ zwracany dla kilku metod asynchronicznych został zmieniony z Task na ValueTask Niska
Adnotacja Relational:TypeMapping jest teraz po prostu TypeMapping Niska
Tabela ToTable w typie pochodnym zgłasza wyjątek Niska
Program EF Core nie wysyła już pragma dla wymuszania klucza FK SQLite Niska
Microsoft.EntityFrameworkCore.Sqlite teraz zależy od SQLitePCLRaw.bundle_e_sqlite3 Niska
Wartości guid są teraz przechowywane jako TEKST w sqlite Niska
Wartości znaków są teraz przechowywane jako TEKST w sqlite Niska
Identyfikatory migracji są teraz generowane przy użyciu niezmiennego kalendarza kultury Niska
Informacje/metadane rozszerzenia zostały usunięte z rozszerzenia IDbContextOptionsExtension Niska
Nazwa elementu LogQueryPossibleExceptionWithAggregateOperator została zmieniona Niska
Wyjaśnienie interfejsu API dla nazw ograniczeń klucza obcego Niska
IRelationalDatabaseCreator.HasTables/HasTablesAsync zostały upublicznione Niska
Microsoft.EntityFrameworkCore.Design jest teraz pakietem DevelopmentDependency Niska
SQLitePCL.raw zaktualizowano do wersji 2.0.0 Niska
NetTopologySuite zaktualizowano do wersji 2.0.0 Niska
Element Microsoft.Data.SqlClient jest używany zamiast Elementu System.Data.SqlClient Niska
Należy skonfigurować wiele niejednoznacznych relacji odwołujących się do siebie Niska
Parametr DbFunction.Schema jest pusty lub ma wartość null, konfiguruje go tak, aby był w domyślnym schemacie modelu Niska
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 może przekonwertować wyrażenia będącego częścią zapytania na sql lub parametr, automatycznie ocenił wyrażenie na kliencie. Domyślnie ocena klienta potencjalnie kosztownych wyrażeń wyzwoliła ostrzeżenie.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core zezwala na ocenę na kliencie tylko wyrażeń w projekcji najwyższego poziomu (ostatnie Select() wywołanie zapytania). 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 Where() wywołaniu, którego nie można przetłumaczyć, może spowodować przeniesienie wszystkich wierszy z tabeli z serwera bazy danych oraz filtr do zastosowania na kliencie. 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 powodujące niezgodność między wydaniami.

Środki zaradcze

Jeśli nie można w pełni przetłumaczyć zapytania, napisz ponownie zapytanie w formularzu, który można przetłumaczyć, lub użyj AsEnumerable()metody , ToList()lub podobnej do jawnego przywrócenia danych do klienta, gdzie można go 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 anonsów problemów nr 325

Stare zachowanie

Przed ASP.NET Core 3.0, po dodaniu odwołania do pakietu do Microsoft.AspNetCore.App programu lub Microsoft.AspNetCore.All, będzie to obejmować program EF Core i niektórych dostawców danych ef Core, takich jak dostawca programu 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 programu EF Core wymaga różnych kroków w zależności od tego, czy aplikacja docelowa 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 środowisko pobierania platformy EF Core jest takie samo we wszystkich dostawcach, obsługiwanych implementacjach platformy .NET i typach aplikacji. Deweloperzy mogą teraz kontrolować dokładnie, kiedy dostawcy danych EF Core i 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 ją jako zależność narzędziową przy użyciu pliku manifestu narzędzia.

Zmiany o niskim wpływie

Zmieniono nazwy z baz danychSql, ExecuteSql i ExecuteSqlAsync

Problem ze śledzeniem 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. 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. 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

Przełącz się, aby użyć nowych nazw metod.

Metoda FromSql, jeśli jest używana z procedurą składowaną, nie może składać się

Problem ze śledzeniem nr 15392

Stare zachowanie

Przed programem EF Core 3.0 metoda FromSql próbowała wykryć, czy przekazany program SQL może się składać. To zrobiło ocenę klienta, gdy sql nie było komponowalne, 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, powodując zapytanie podrzędne. Dlatego jeśli używasz procedury składowanej ze składem, otrzymasz wyjątek dla 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 katalogów głównych zapytań

Problem ze śledzeniem nr 15704

Stare zachowanie

Przed programem EF Core 3.0 FromSql można określić metodę w dowolnym miejscu w zapytaniu.

Nowe zachowanie

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

Dlaczego

Określanie FromSql dowolnego miejsca innego niż na obiekcie nie miało żadnego dodatkowego DbSet znaczenia lub wartości dodanej i może spowodować niejednoznaczność w niektórych scenariuszach.

Środki zaradcze

FromSql wywołania powinny być przenoszone bezpośrednio na DbSet element, do którego mają zastosowanie.

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

Problem ze śledzeniem 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. Jest to zgodne z zachowaniem śledzenia zapytań. Na przykład to zapytanie:

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

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, program EF Core przechowuje tymczasową wartość klucza w ramach informacji śledzenia jednostki i pozostawia właściwość klucza bez zmian.

Dlaczego

Ta zmiana została wprowadzona, aby zapobiec błędnemu utracie wartości kluczy tymczasowych, gdy jednostka, która została wcześniej śledzona przez niektóre DbContext wystąpienie, zostanie przeniesiona do innego DbContext wystąpienia.

Środki zaradcze

Aplikacje, które przypisują wartości klucza podstawowego do kluczy obcych w celu tworzenia skojarzeń między jednostkami, mogą zależeć od starego zachowania, jeśli klucze podstawowe są generowane i należą do jednostek 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 honoruje wartości kluczy generowanych przez magazyn

Problem ze śledzeniem nr 14616

Stare zachowanie

Przed programem EF Core 3.0 nieśledzony obiekt znaleziony DetectChanges przez zostanie śledzony w Added stanie i wstawiony jako nowy wiersz po SaveChanges wywołaniu.

Nowe zachowanie

Począwszy od programu EF Core 3.0, jeśli jednostka używa wygenerowanych wartości klucza i ustawiono pewną wartość klucza, jednostka zostanie śledzona w Modified stanie. 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łączonym grafami jednostek 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 3.0 program EF Core zastosował akcje kaskadowe (usuwanie jednostek zależnych po usunięciu wymaganego podmiotu zabezpieczeń lub zerwaniu relacji z wymaganym podmiotem zabezpieczeń) 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 metody context.Remove() w celu usunięcia jednostki głównej spowoduje natychmiastowe ustawienie Deleted wszystkich powiązanych powiązanych wymaganych zależności.

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. Przykład:

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

Problem ze śledzeniem nr 18022

Stare zachowanie

Przed 3.0 chętne ładowanie nawigacji kolekcji za pośrednictwem Include operatorów spowodowało wygenerowanie wielu zapytań w relacyjnej bazie danych, po jednym dla każdego powiązanego typu jednostki.

Nowe zachowanie

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

Dlaczego

Wykonywanie wielu zapytań w celu zaimplementowania pojedynczego zapytania LINQ spowodowało wiele problemów, w tym negatywną wydajność, ponieważ wiele pasków baz danych było niezbędnych, a problemy z współistnieniem danych, ponieważ każde zapytanie może 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 uzyskać bardziej wydajne pisanie zapytań.

**

Funkcja DeleteBehavior.Restrict ma semantykę czystszą

Problem ze śledzeniem 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, zapewnia, DeleteBehavior.Restrict że klucze obce są tworzone za pomocą Restrict semantyki — to znaczy bez kaskadowych— nie ma wpływu na naruszenie ograniczeń — bez wpływu również na poprawkę wewnętrzną ef.

Dlaczego

Ta zmiana została wprowadzona, aby poprawić środowisko do korzystania 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. Podobnie są one często mapowane na widoki, 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 nullnull obiekt, zostaną zwrócone zamiast jednostki, jeśli ten problem ma zastosowanie do danego scenariusza, dodaj również logikę do obsługi null wyników.

Zmieniono interfejs API konfiguracji dla relacji typu należącego do użytkownika

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(). Przykład:

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

Konfiguracja związana z relacją między właścicielem i właścicielem powinna być teraz łańcuchowa po WithOwner() podobnej do konfiguracji innych relacji. Mimo że konfiguracja samego typu własności nadal będzie łańcuchowa po OwnsOne()/OwnsMany(). 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()metody , HasOne()lub Set() z obiektem docelowym typu należącego do firmy 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 programem EF Core 3.0, jeśli OrderDetails jest własnością Order lub jawnie zamapowany na tę samą tabelę OrderDetails , wystąpienie zawsze było wymagane podczas dodawania nowego Orderelementu .

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core umożliwia dodanie Order elementu bez elementu OrderDetails i mapowania wszystkich OrderDetails właściwości z wyjątkiem klucza podstawowego do kolumn dopuszczanych do wartości null. Podczas wykonywania zapytań względem zestawów OrderDetailsnull EF Core, jeśli którakolwiek z jej wymaganych właściwości nie ma wartości lub jeśli nie ma wymaganych właściwości oprócz klucza podstawowego, a wszystkie właściwości to null.

Środki zaradcze

Jeśli model ma współużytkowanie tabeli zależne od wszystkich kolumn opcjonalnych, ale nawigacja wskazująca ją nie powinna być null zgodna z oczekiwaniami, należy zmodyfikować aplikację tak, aby obsługiwała przypadki, gdy nawigacja to null. Jeśli nie jest to możliwe, wymagana właściwość powinna zostać dodana do typu jednostki lub co najmniej jedna właściwość powinna mieć przypisaną wartość innąnull niż.

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

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 programem EF Core 3.0, jeśli OrderDetails jest własnością Order lub jawnie zamapowany na tę samą tabelę, aktualizacja tylko OrderDetails nie Version zaktualizuje wartości na kliencie, a następna aktualizacja zakończy się niepowodzeniem.

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core propaguje nową Version wartość, 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żytujące tabelę muszą zawierać właściwość zamapowana na kolumnę 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 programem EF Core 3.0 można odpytować należące do nich jednostki jako inne nawigacje.

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

Nowe zachowanie

Począwszy od wersji 3.0, program EF Core zgłosi zgłoszenie, jeśli śledzenie projektów zapytań jest własnością jednostki 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 programem EF Core 3.0 ShippingAddress właściwość zostanie zamapowana na oddzielne kolumny i BulkOrderOrder domyślnie.

Nowe zachowanie

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

Dlaczego

Stary behavoir był nieoczekiwany.

Ś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 właściwości klucza obcego nie jest już zgodna z tą samą nazwą co właściwość główna

Problem ze śledzeniem 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 programem EF Core 3.0 CustomerId właściwość będzie używana dla klucza obcego zgodnie z konwencją. Jeśli jednak jest typem należącym do Order użytkownika, będzie to również CustomerId klucz podstawowy i zwykle nie jest to oczekiwane.

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. 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 typu należącego do użytkownika.

Ś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 przed ukończeniem transakcjiScope

Problem ze śledzeniem nr 14218

Stare zachowanie

Przed programem 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());
        context.SaveChanges();

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

        var categories = context.ProductCategories().ToList();
    }
}

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 TransactionScopepliku . Nowe zachowanie jest również zgodne z platformą EF6.

Środki zaradcze

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

using (new TransactionScope())
{
    using (AdventureWorks context = new AdventureWorks())
    {
        context.Database.OpenConnection();
        context.ProductCategories.Add(new ProductCategory());
        context.SaveChanges();

        var categories = context.ProductCategories().ToList();
        context.Database.CloseConnection();
    }
}

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

Problem ze śledzeniem 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 programu EF Core 3.0, każda właściwość klucza całkowitego pobiera własny generator wartości podczas korzystania z bazy danych w pamięci. 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 tworzenia kopii zapasowej zostałoby ustawione bezpośrednio, jeśli jest znane.

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. 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ć pole do jawnego użycia. 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 programu EF Core 3.0, właściwość tylko dla 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 programem EF Core 3.0 wywoływanie AddDbContext lub AddDbContextPool rejestrowanie usług rejestrowania i buforowania pamięci przy użyciu di za pomocą wywołań AddLogging i AddMemoryCache.

Nowe zachowanie

Począwszy od programu EF Core 3.0 i AddDbContextAddDbContextPool nie zarejestruje już tych usług za pomocą wstrzykiwania 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

Problem ze śledzeniem nr 12905

Stare zachowanie

Przed programem EF Core 3.0 metody wywołujące AddEntityFramework* będą również rejestrować usługi buforowania pamięci z di bez limitu 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 wywołania AddEntityFramework* nie jest konieczne, jeśli AddDbContext wywołana jest również funkcja lub AddDbContextPool . W związku z tym najlepszym ograniczeniem 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 programem EF Core 3.0 wywołanie spowoduje wykrycie DbContext.Entry zmian dla wszystkich śledzonych jednostek. Dzięki temu stan uwidoczniony w obiekcie EntityEntry był aktualny.

Nowe zachowanie

Począwszy od programu EF Core 3.0, wywołanie DbContext.Entry spowoduje teraz tylko próbę wykrycia zmian w danej jednostce i wszelkich śledzonych podmiotów zabezpieczeń powiązanych z nią. 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 ustawiona na false wartość , 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 wszystkie śledzone jednostki.

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 metody Entry , aby upewnić się, że zachowanie przed 3.0.

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

Problem ze śledzeniem nr 14617

Stare zachowanie

Przed programem EF Core 3.0 string i byte[] właściwościami klucza można użyć bez jawnego ustawienia 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 programu EF Core 3.0 zostanie zgłoszony wyjątek wskazujący, że nie ustawiono żadnej 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 korzystanie z innych funkcji i usuwa niektóre przypadki patologicznego zachowania, takiego jak eksplozja 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. Nie jest to 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 monitorze problemów platformy EF Core w usłudze GitHub, aby poinformować nas, jak używasz ILoggerFactory takiego rozwiązania, abyśmy mogli lepiej zrozumieć, jak nie przerywać tego ponownie w przyszłości.

Serwery proxy ładowania z opóźnieniem nie zakładają już, że właściwości nawigacji są w pełni ładowane

Problem ze śledzeniem nr 12780

Stare zachowanie

Przed ef Core 3.0, gdy DbContext obiekt został usunięty, nie było możliwości poznania, czy dana właściwość nawigacji na jednostce uzyskanej 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 no-op.

Nowe zachowanie

Począwszy od programu EF Core 3.0, serwery proxy śledzą, czy właściwość nawigacji jest ł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ł ładować z opóźnieniem z usuniętym kontekstem lub skonfigurować go tak, aby był no-op 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 zwiększenia kodu aplikacji poprzez bardziej jawne 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 zignorowane) za pomocą konfiguracji w pliku DbContextOptionsBuilder. Przykład:

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

Nowe zachowanie funkcji HasOne/HasMany o nazwie z jednym ciągiem

Problem ze śledzeniem nr 9171

Stare zachowanie

Przed programem EF Core 3.0 wywołanie HasOne kodu lub HasMany za pomocą jednego ciągu zostało zinterpretowane w mylący sposób. Przykład:

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

Kod wygląda tak, jakby odnosił Samurai się do innego typu jednostki przy użyciu Entrance właściwości nawigacji, 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 programu EF Core 3.0, powyższy kod teraz robi to, jak wyglądało to wcześniej.

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ć za pośrednictwem jawnego przekazywania null nazwy właściwości nawigacji. Przykład:

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

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

Problem ze śledzeniem nr 15184

Stare zachowanie

Następujące metody asynchroniczne zwróciły wcześniej element Task<T>:

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

Nowe zachowanie

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

Dlaczego

Ta zmiana zmniejsza liczbę alokacji sterty poniesionej podczas wywoływania tych metod, zwiększają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()elementu ) zwykle wymaga przekonwertowania zwróconego elementu ValueTask<T> na obiekt Task<T> przez wywołanie AsTask() metody . 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 adnotacji dla adnotacji mapowania typów to "Relational:TypeMapping".

Nowe zachowanie

Nazwa adnotacji 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 aplikacji, które uzyskują dostęp do mapowania typów bezpośrednio jako adnotacja, co nie jest typowe. Najbardziej odpowiednią akcją do naprawienia jest użycie powierzchni interfejsu API do uzyskiwania dostępu do mapowań typów zamiast bezpośredniego używania adnotacji.

Tabela ToTable w typie pochodnym zgłasza wyjątek

Problem ze śledzeniem nr 11811

Stare zachowanie

Przed programem EF Core 3.0 wywołanie typu pochodnego zostanie zignorowane, ponieważ tylko strategia mapowania dziedziczenia była TPH, ToTable() gdy nie jest to prawidłowe.

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 jest prawidłowe mapowanie 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.

Element ForSqlServerHasIndex został zastąpiony hasindex

Problem ze śledzeniem nr 12366

Stare zachowanie

Przed programem EF Core 3.0 ForSqlServerHasIndex().ForSqlServerInclude() udostępniono sposób konfigurowania kolumn używanych z INCLUDEprogramem .

Nowe zachowanie

Począwszy od programu EF Core 3.0, korzystanie z Include indeksu jest teraz obsługiwane na poziomie relacyjnym. Użyj witryny HasIndex().ForSqlServerInclude().

Dlaczego

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

Środki zaradcze

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

Zmiany interfejsu API metadanych

Problem ze śledzeniem 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

Problem ze śledzeniem nr 214

Nowe zachowanie

Metody rozszerzenia specyficzne dla dostawcy zostaną spłaszczone:

  • 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

Począwszy od programu EF Core 3.0, program EF Core nie jest PRAGMA foreign_keys = 1 już wysyłany 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 teraz zależy 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 programu EF Core 3.0, program EF Core używa programu 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

Problem ze śledzeniem 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

Format binarny 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 ponieważ domyślny format parametrów i stałych uległ zmianie, prawdopodobnie trzeba będzie podjąć działania w przypadku większości scenariuszy obejmujących identyfikatory 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 sored 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

Problem ze śledzeniem 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 dostarczania 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.

Nazwa elementu LogQueryPossibleExceptionWithAggregateOperator została zmieniona

Problem ze śledzeniem nr 10985

Zmiana

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ą". 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". 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

Problem ze śledzeniem 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 spoza ef podczas określania, czy należy 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 programem EF Core 3.0 Microsoft.EntityFrameworkCore.Design był zwykłym pakietem NuGet, którego zestaw może być przywoływane przez projekty, które od niego zależą.

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ć. Utworzenie pakietu jako elementu DevelopmentDependency wzmacnia to zalecenie.

Środki zaradcze

Jeśli chcesz odwołać się do tego pakietu, aby zastąpić zachowanie czasu projektowania platformy EF Core, 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 biblioteki 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 dużego zamknięcia pakietów przechodnich do pracy.

Środki zaradcze

SqLitePCL.raw w wersji 2.0.0 zawiera pewne zmiany powodujące niezgodność. Aby uzyskać szczegółowe informacje, zobacz informacje o wersji.

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ść. Aby uzyskać szczegółowe informacje, zobacz informacje o wersji.

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

Problem ze śledzeniem nr 15636

Stare zachowanie

Microsoft.EntityFrameworkCore.SqlServer wcześniej zależało od elementu 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. 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. Przykład:

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

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

Parametr DbFunction.Schema jest pusty lub ma wartość null, konfiguruje go tak, aby był w domyślnym schemacie 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 schemat był pustym sposobem traktowania tej funkcji jest wbudowany, ale ta logika ma zastosowanie tylko dla programu SqlServer, 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

Problem ze śledzeniem nr 15498

Program EF Core 3.0 jest przeznaczony dla platformy .NET Standard 2.1, co jest zmianą powodującą niezgodność, która wyklucza 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

Problem ze śledzeniem 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 bazy danych SQL na Debug, jawnie skonfiguruj poziom w OnConfiguring systemie lub AddDbContext:

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