Zásadní změny zahrnuté v EF Core 3.x

Následující změny rozhraní API a chování mají potenciál přerušit stávající aplikace při upgradu na verzi 3.x. Změny, které očekáváme, že ovlivní jenom zprostředkovatele databáze, jsou zdokumentované ve změnách zprostředkovatele.

Souhrn

Změna způsobující chybu Dopad
Dotazy LINQ se už v klientovi nevyhodnocují. Vyšší
Nástroj příkazového řádku EF Core, dotnet ef, už není součástí sady .NET Core SDK. Vyšší
DetectChanges respektuje hodnoty klíče generovaného úložištěm Vyšší
Byly přejmenovány FromSql, ExecuteSql a ExecuteSqlAsync. Vyšší
Typy dotazů se konsolidují s typy entit. Vyšší
Entity Framework Core už není součástí sdílené architektury ASP.NET Core. Medium
Kaskádové odstranění teď probíhá okamžitě ve výchozím nastavení. Medium
Načítání souvisejících entit teď probíhá v jednom dotazu. Medium
DeleteBehavior.Restrict má čistější sémantiku Medium
Změnilo se rozhraní API konfigurace pro relace vlastněných typů. Medium
Každá vlastnost používá nezávislé generování celočíselného klíče v paměti. Medium
Dotazy bez sledování už neprovádějí překlad identit. Medium
Změny rozhraní API metadat Medium
Změny rozhraní API metadat specifických pro zprostředkovatele Medium
PoužitíRowNumberForPaging bylo odebráno. Medium
Metoda FromSql při použití s uloženou procedurou se nedá sestavit. Medium
Metody FromSql je možné zadat pouze v kořenech dotazů. nízkou
Hodnoty dočasných klíčů už nejsou nastaveny na instance entit. nízkou
Závislé entity sdílející tabulku s objektem zabezpečení jsou teď volitelné. nízkou
Všechny entity sdílející tabulku se sloupcem tokenu souběžnosti musí namapovat na vlastnost. nízkou
Vlastněné entity nelze dotazovat bez vlastníka pomocí sledovacího dotazu. nízkou
Zděděné vlastnosti z nemapovaných typů se teď mapují na jeden sloupec pro všechny odvozené typy. nízkou
Konvence vlastností cizího klíče už neodpovídá stejnému názvu jako hlavní vlastnost. nízkou
Připojení k databázi je nyní zavřené, pokud se už nepoužívá před dokončením TransactionScope. nízkou
Backing fields are used by default nízkou
Vyvolání, pokud se najde více kompatibilních záložních polí nízkou
Názvy vlastností jen pro pole by se měly shodovat s názvem pole. nízkou
AddDbContext/AddDbContextPool už nevolá AddLogging a AddMemoryCache nízkou
AddEntityFramework* přidá IMemoryCache s limitem velikosti. nízkou
DbContext.Entry teď provádí místní detektivy DetectChanges. nízkou
Klíče pole řetězců a bajtů nejsou ve výchozím nastavení generovány klientem. nízkou
ILoggerFactory je teď vymezená služba nízkou
Opožděné načítání proxy serverů už nepředpokládá, že jsou plně načteny navigační vlastnosti. nízkou
Nadměrné vytváření interních poskytovatelů služeb je teď ve výchozím nastavení chybou. nízkou
Nové chování pro HasOne/HasMany volaný jedním řetězcem nízkou
Návratový typ pro několik asynchronních metod byl změněn z Task na ValueTask. nízkou
Relační poznámka:TypeMapping je teď jenom TypeMapping. nízkou
ToTable pro odvozený typ vyvolá výjimku nízkou
EF Core už neodesílá direktivu pragma pro vynucení FK SQLite nízkou
Microsoft.EntityFrameworkCore.Sqlite teď závisí na SQLitePCLRaw.bundle_e_sqlite3 nízkou
Hodnoty GUID se teď ukládají jako TEXT na SQLite. nízkou
Hodnoty znaků se teď ukládají jako TEXT na SQLite. nízkou
ID migrace se teď generují pomocí kalendáře invariantní jazykové verze. nízkou
Informace o rozšíření a metadata byly odebrány z IDbContextOptionsExtension nízkou
LogQueryPossibleExceptionWithAggregateOperator byl přejmenován. nízkou
Objasnění názvů omezení cizího klíče rozhraní API nízkou
IRelationalDatabaseCreator.HasTables/HasTablesAsync byly veřejně zpřístupněny nízkou
Microsoft.EntityFrameworkCore.Design je teď balíček DevelopmentDependency nízkou
Aktualizace SQLitePCL.raw na verzi 2.0.0 nízkou
NetTopologySuite byl aktualizován na verzi 2.0.0. nízkou
Microsoft.Data.SqlClient se používá místo System.Data.SqlClient. nízkou
Je potřeba nakonfigurovat několik nejednoznačných vztahů odkazujících na sebe. nízkou
DbFunction.Schema má hodnotu null nebo prázdný řetězec konfiguruje, aby byl ve výchozím schématu modelu. nízkou
EF Core 3.0 cílí na .NET Standard 2.1 místo na vrácení .NET Standard 2.0
Provádění dotazů se protokoluje na úrovni ladění– Vráceno

Změny s vysokým dopadem

Dotazy LINQ se už v klientovi nevyhodnocují.

Problém sledování č. 14935– Viz také problém č. 12795

Staré chování

Před verzí 3.0, když EF Core nemohl převést výraz, který byl součástí dotazu, na JAZYK SQL nebo parametr, automaticky vyhodnotil výraz v klientovi. Ve výchozím nastavení se při vyhodnocování potenciálně drahých výrazů aktivovalo upozornění.

Nové chování

Od verze 3.0 EF Core povoluje vyhodnocení výrazů pouze v projekci nejvyšší úrovně (poslední Select() volání dotazu). Pokud výrazy v jakékoli jiné části dotazu nelze převést na SQL nebo parametr, vyvolá se výjimka.

Proč

Automatické vyhodnocení dotazů klientů umožňuje provádět mnoho dotazů i v případě, že se důležité části nedají přeložit. Toto chování může vést k neočekávanému a potenciálně škodlivému chování, které se může projevit pouze v produkčním prostředí. Například podmínka ve Where() volání, která se nedá přeložit, může způsobit přenos všech řádků z tabulky z databázového serveru a použití filtru v klientovi. Tato situace se může snadno zrušit, pokud tabulka obsahuje jen několik řádků ve vývoji, ale při přesunu aplikace do produkčního prostředí, kde tabulka může obsahovat miliony řádků, může být obtížné. Upozornění hodnocení klientů se také ukázala jako příliš snadná ignorovat během vývoje.

Kromě toho může automatické vyhodnocení klienta vést k problémům, při kterých zlepšení překladu dotazů pro konkrétní výrazy způsobilo neúmyslné zásadní změny mezi verzemi.

Omezení rizik

Pokud dotaz nelze plně přeložit, přepište dotaz ve formuláři, který lze přeložit, nebo použijte AsEnumerable(), ToList()nebo podobně jako explicitně převést data zpět do klienta, kde je pak lze dále zpracovat pomocí LINQ-to-Objects.

Změny se středním dopadem

Entity Framework Core už není součástí sdílené architektury ASP.NET Core.

Oznámení o problému sledování č. 325

Staré chování

Než ASP.NET Core 3.0 přidáte odkaz na Microsoft.AspNetCore.App balíček nebo Microsoft.AspNetCore.All, bude obsahovat EF Core a některé z poskytovatelů dat EF Core, jako je poskytovatel SQL Serveru.

Nové chování

Od verze 3.0 sdílená architektura ASP.NET Core nezahrnuje EF Core ani žádné poskytovatele dat EF Core.

Proč

Před touto změnou se získání EF Core vyžadovalo různé kroky v závislosti na tom, jestli aplikace cílí na ASP.NET Core a SQL Server, nebo ne. Upgrade ASP.NET Core také vynutil upgrade EF Core a poskytovatele SQL Serveru, což není vždy žádoucí.

Díky této změně je zkušenost se získáním EF Core stejná napříč všemi poskytovateli, podporovanými implementacemi .NET a typy aplikací. Vývojáři teď také můžou přesně určit, kdy se upgradují poskytovatelé dat EF Core a EF Core.

Omezení rizik

Pokud chcete použít EF Core v aplikaci ASP.NET Core 3.0 nebo jakékoli jiné podporované aplikaci, explicitně přidejte odkaz na balíček na poskytovatele databáze EF Core, kterého bude vaše aplikace používat.

Nástroj příkazového řádku EF Core, dotnet ef, už není součástí sady .NET Core SDK.

Problém se sledováním č. 14016

Staré chování

Před verzí 3.0 dotnet ef byl nástroj součástí sady .NET Core SDK a byl snadno dostupný pro použití z příkazového řádku z libovolného projektu bez nutnosti dalších kroků.

Nové chování

Počínaje verzí 3.0 sada .NET SDK nástroj neobsahuje dotnet ef , takže než ho budete moct použít, musíte ho explicitně nainstalovat jako místní nebo globální nástroj.

Proč

Tato změna nám umožňuje distribuovat a aktualizovat dotnet ef jako běžný nástroj .NET CLI na NuGetu, který je konzistentní se skutečností, že EF Core 3.0 je také vždy distribuován jako balíček NuGet.

Omezení rizik

Pokud chcete spravovat migrace nebo generování uživatelského rozhraní DbContext, nainstalujte dotnet-ef ho jako globální nástroj:

dotnet tool install --global dotnet-ef

Můžete ho také získat místním nástrojem, když obnovíte závislosti projektu, který ho deklaruje jako závislost nástrojů pomocí souboru manifestu nástroje.

Změny s nízkým dopadem

Byly přejmenovány FromSql, ExecuteSql a ExecuteSqlAsync.

Sledování problému č. 10996

Důležité

ExecuteSqlCommand a ExecuteSqlCommandAsync jsou zastaralé. Místo toho použijte tyto metody.

Staré chování

Před EF Core 3.0 byly tyto názvy metod přetíženy tak, aby fungovaly s normálním řetězcem nebo řetězcem, který by měl být interpolován do SQL a parametrů.

Nové chování

Počínaje EF Core 3.0 použijte FromSqlRawExecuteSqlRawa ExecuteSqlRawAsync vytvořte parametrizovaný dotaz, ve kterém se parametry předávají odděleně od řetězce dotazu. Příklad:

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

ExecuteSqlInterpolatedExecuteSqlInterpolatedAsync Slouží FromSqlInterpolatedk vytvoření parametrizovaného dotazu, ve kterém se parametry předávají jako součást interpolovaného řetězce dotazu. Příklad:

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

Všimněte si, že oba výše uvedené dotazy vytvoří stejný parametrizovaný SQL se stejnými parametry SQL.

Proč

Přetížení metod, jako je tato, usnadňuje náhodné volání nezpracované řetězcové metody, když záměr bylo volat interpolovanou řetězcovou metodu a naopak. To může vést k tomu, že dotazy nebudou parametrizovány, když by měly být.

Omezení rizik

Přepněte na použití nových názvů metod.

Metoda FromSql při použití s uloženou procedurou se nedá sestavit.

Problém se sledováním č. 15392

Staré chování

Před EF Core 3.0 se metoda FromSql pokusila zjistit, jestli se předaný SQL může skládat. Provedlo vyhodnocení klienta, když sql nebyl kompozovatelný jako uložená procedura. Následující dotaz fungoval spuštěním uložené procedury na serveru a provedením FirstOrDefault na straně klienta.

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

Nové chování

Od EF Core 3.0 se EF Core nepokusí analyzovat SQL. Takže pokud vytváříte po FromSqlRaw/FromSqlInterpolated, EF Core vytvoří SQL tím, že způsobí dílčí dotaz. Pokud tedy používáte uloženou proceduru se složením, získáte výjimku pro neplatnou syntaxi SQL.

Proč

EF Core 3.0 nepodporuje automatické vyhodnocování klientů, protože to bylo náchylné k chybám, jak je vysvětleno zde.

Omezení rizik

Pokud používáte uloženou proceduru v FromSqlRaw/FromSqlInterpolated, víte, že ji nelze sestavit, takže můžete přidat AsEnumerable/AsAsyncEnumerable přímo za volání metody FromSql, abyste se vyhnuli jakékoli složení na straně serveru.

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

Metody FromSql je možné zadat pouze v kořenech dotazů.

Problém se sledováním č. 15704

Staré chování

Před EF Core 3.0 může FromSql být metoda zadána kdekoli v dotazu.

Nové chování

Od EF Core 3.0 je možné nové FromSqlRaw metody a FromSqlInterpolated metody (které nahrazují FromSql) zadat pouze u kořenových dotazů, tj. přímo na DbSet<>. Pokus o zadání kdekoli jinde způsobí chybu kompilace.

Proč

Určení FromSql libovolného jiného DbSet místa než v případě, že nemá žádný přidaný význam nebo přidanou hodnotu, a v určitých scénářích by mohlo dojít k nejednoznačnosti.

Omezení rizik

FromSql vyvolání by mělo být přesunuto tak, aby byly přímo na DbSet tom, na které se vztahují.

Dotazy bez sledování už neprovádějí překlad identit.

Problém se sledováním č. 13518

Staré chování

Před EF Core 3.0 by se stejná instance entity použila pro každý výskyt entity s daným typem a ID. Odpovídá chování sledovacích dotazů. Například tento dotaz:

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

vrátí stejnou Category instanci pro každou Product přidruženou k dané kategorii.

Nové chování

Od EF Core 3.0 se vytvoří různé instance entit, když se entita s daným typem a ID zjistí na různých místech ve vráceném grafu. Výše uvedený dotaz například vrátí novou Category instanci pro každou Product z nich, i když jsou dva produkty přidružené ke stejné kategorii.

Proč

Řešení identit (tj. určení, že entita má stejný typ a ID jako dříve zjištěná entita) zvyšuje další výkon a režii paměti. Obvykle se to spouští čítače, proč se dotazy bez sledování používají na prvním místě. I když může být řešení identit někdy užitečné, není potřeba, pokud se entity mají serializovat a odesílat klientovi, což je běžné pro dotazy bez sledování.

Omezení rizik

Pokud se vyžaduje překlad identity, použijte sledovací dotaz.

Hodnoty dočasných klíčů už nejsou nastaveny na instance entit.

Problém se sledováním č. 12378

Staré chování

Před EF Core 3.0 byly dočasné hodnoty přiřazeny ke všem vlastnostem klíče, které by později měly skutečnou hodnotu vygenerovanou databází. Obvykle byly tyto dočasné hodnoty velkými zápornými čísly.

Nové chování

Od verze 3.0 ef Core ukládá hodnotu dočasného klíče jako součást informací o sledování entity a ponechá samotnou vlastnost klíče beze změny.

Proč

Tato změna byla provedena, aby se dočasné hodnoty klíče chybně staly trvalými, když se entita, která byla dříve sledována nějakou DbContext instancí, přesune do jiné DbContext instance.

Omezení rizik

Aplikace, které přiřazují hodnoty primárního klíče cizím klíčům k formování přidružení mezi entitami, můžou záviset na starém chování, pokud jsou primární klíče vygenerovány do úložiště a patří do entit ve Added stavu. Tomu se můžete vyhnout:

  • Nepoužívá se klíče generované úložištěm.
  • Nastavení navigačních vlastností pro relace formulářů místo nastavení hodnot cizího klíče
  • Získejte skutečné hodnoty dočasného klíče z informací o sledování entity. Vrátí například context.Entry(blog).Property(e => e.Id).CurrentValue dočasnou hodnotu, i když blog.Id nebyla nastavena.

DetectChanges respektuje hodnoty klíče generovaného úložištěm

Problém se sledováním č. 14616

Staré chování

Před EF Core 3.0 by se nesledovaná entita nalezená DetectChanges uživatelem sledovala ve Added stavu a při zavolání se vložila jako nový řádek SaveChanges .

Nové chování

Od EF Core 3.0 platí, že pokud entita používá vygenerované hodnoty klíče a nastaví se nějaká hodnota klíče, bude entita Modified sledována ve stavu. To znamená, že se předpokládá, že existuje řádek entity a po SaveChanges zavolání se aktualizuje. Pokud hodnota klíče není nastavená nebo pokud typ entity nepoužívá vygenerované klíče, bude nová entita stále sledována jako Added v předchozích verzích.

Proč

Tato změna byla provedena, aby byla jednodušší a konzistentnější práce s odpojenými grafy entit při používání klíčů generovaných úložištěm.

Omezení rizik

Tato změna může aplikaci přerušit, pokud je typ entity nakonfigurovaný tak, aby používal generované klíče, ale hodnoty klíčů jsou explicitně nastaveny pro nové instance. Oprava spočívá v explicitní konfiguraci vlastností klíče tak, aby nepoužíly vygenerované hodnoty. Například s rozhraním API fluent:

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

Nebo s datovými poznámkami:

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

Kaskádové odstranění teď probíhá okamžitě ve výchozím nastavení.

Problém se sledováním č. 10114

Staré chování

Před 3.0 ef Core použil kaskádové akce (odstranění závislých entit při odstranění požadovaného objektu zabezpečení nebo při zrušení vztahu k požadovanému objektu zabezpečení) neproběhly, dokud se nezavolala funkce SaveChanges.

Nové chování

Od verze 3.0 ef Core použije kaskádové akce hned po zjištění aktivační podmínky. Například voláním context.Remove() k odstranění entity objektu zabezpečení dojde k okamžitému Deleted nastavení všech sledovaných požadovaných závislých závislostí.

Proč

Tato změna byla provedena, aby se zlepšilo prostředí pro scénáře datových vazeb a auditování, ve kterých je důležité pochopit, které entity se před zavoláním odstraníSaveChanges.

Omezení rizik

Předchozí chování lze obnovit pomocí nastavení .context.ChangeTracker Příklad:

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

Problém se sledováním č. 18022

Staré chování

Před 3.0 dychtivým načítáním navigačních panelů kolekcí prostřednictvím Include operátorů způsobilo generování více dotazů v relační databázi, jedno pro každý související typ entity.

Nové chování

Od verze 3.0 EF Core vygeneruje jeden dotaz s JOINs v relačních databázích.

Proč

Vydávání více dotazů pro implementaci jednoho dotazu LINQ způsobilo celou řadu problémů, včetně negativního výkonu, protože bylo nutné provést několik opakování databáze, a problémy s koherentností dat, protože každý dotaz může sledovat jiný stav databáze.

Omezení rizik

I když technicky vzato se nejedná o zásadní změnu, mohlo by to mít značný vliv na výkon aplikace, když jeden dotaz obsahuje velký počet Include operátorů na navigaci v kolekci. Další informace a přepisování dotazů efektivnějším způsobem najdete v tomto komentáři .

**

DeleteBehavior.Restrict má čistější sémantiku

Problém se sledováním č. 12661

Staré chování

Před 3.0 DeleteBehavior.Restrict se v databázi vytvořily cizí klíče s sémantikou Restrict , ale také se změnily interní opravy nejevným způsobem.

Nové chování

Počínaje verzí 3.0 zajistíte, DeleteBehavior.Restrict že se vytvoří cizí klíče s sémantikou Restrict – to znamená, že žádné kaskády; vyvolání porušení omezení – bez dopadu také na interní opravu EF.

Proč

Tato změna byla provedena, aby se zlepšilo prostředí pro používání DeleteBehavior intuitivním způsobem bez neočekávaných vedlejších účinků.

Omezení rizik

Předchozí chování lze obnovit pomocí .DeleteBehavior.ClientNoAction

Typy dotazů se konsolidují s typy entit.

Problém se sledováním č. 14194

Staré chování

Před EF Core 3.0 byly typy dotazů prostředkem pro dotazování na data, která nedefinuje primární klíč strukturovaným způsobem. To znamená, že typ dotazu byl použit pro mapování typů entit bez klíčů (s větší pravděpodobností ze zobrazení, ale pravděpodobně z tabulky), zatímco byl použit běžný typ entity, když byl klíč k dispozici (pravděpodobněji z tabulky, ale možná z zobrazení).

Nové chování

Typ dotazu se teď stává pouze typem entity bez primárního klíče. Typy entit bez klíčů mají stejné funkce jako typy dotazů v předchozích verzích.

Proč

Tato změna byla provedena, aby se snížila nejasnost ohledně účelu typů dotazů. Konkrétně jde o typy entit bez klíčů a vzhledem k tomu, že jsou ze své podstaty jen pro čtení, ale neměly by se používat jenom proto, že typ entity musí být jen pro čtení. Podobně se často mapují na zobrazení, ale to je jenom proto, že zobrazení často nedefinují klíče.

Omezení rizik

Následující části rozhraní API jsou teď zastaralé:

  • ModelBuilder.Query<>() – Místo toho ModelBuilder.Entity<>().HasNoKey() je potřeba volat, aby se typ entity označil jako bez klíčů. Tato konfigurace by se stále nenakonfigurovala konvencí, aby se zabránilo chybné konfiguraci, pokud se očekává primární klíč, ale neodpovídá konvenci.
  • DbQuery<> - Místo toho DbSet<> by se mělo použít.
  • DbContext.Query<>() - Místo toho DbContext.Set<>() by se mělo použít.
  • IQueryTypeConfiguration<TQuery> - Místo toho IEntityTypeConfiguration<TEntity> by se mělo použít.

Poznámka

Kvůli problému ve verzi 3.x při dotazování entit bez klíčů, které mají všechny vlastnosti nastavené na nullnull entitu, se vrátí místo entity, pokud se tento problém týká vašeho scénáře, přidejte logiku pro zpracování null výsledků.

Změnilo se rozhraní API konfigurace pro relace vlastněných typů.

Problém se sledováním č. 12444– Problém se sledováním #9148– Problém se sledováním #14153

Staré chování

Před EF Core 3.0 byla konfigurace vlastněné relace provedena přímo po OwnsOne volání nebo OwnsMany volání.

Nové chování

Počínaje EF Core 3.0 teď existuje rozhraní API fluent ke konfiguraci navigační vlastnosti pro vlastníka pomocí WithOwner(). Příklad:

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

Konfigurace související se vztahem mezi vlastníkem a vlastněným by teď měla být zřetězený podle WithOwner() toho, jak se konfigurují jiné relace. I když by konfigurace vlastního typu byla stále zřetězený po OwnsOne()/OwnsMany(). Příklad:

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
            });
    });

Kromě volání Entity(), HasOne()nebo Set() s vlastním typem cíl nyní vyvolá výjimku.

Proč

Tato změna byla provedena tak, aby se vytvořilo čistější oddělení mezi konfigurací vlastního typu a relace s vlastním typem. To zase odstraňuje nejednoznačnost a nejasnost kolem metod, jako je HasForeignKey.

Omezení rizik

Změňte konfiguraci relací vlastněných typů tak, aby používala novou plochu rozhraní API, jak je znázorněno v předchozím příkladu.

Závislé entity sdílející tabulku s objektem zabezpečení jsou teď volitelné.

Sledování problému č. 9005

Staré chování

Podívejte se například na následující 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; }
}

Před EF Core 3.0, pokud OrderDetails je vlastněna nebo explicitně namapována Order na stejnou tabulku, OrderDetails byla při přidání nové Orderinstance vždy vyžadována instance .

Nové chování

Od verze 3.0 ef Core umožňuje přidat Order bez OrderDetails a mapovat všechny vlastnosti kromě primárního OrderDetails klíče na sloupce s možnou hodnotou null. Při dotazování EF Core se nastaví OrderDetails , null pokud některá z jejích požadovaných vlastností nemá hodnotu nebo pokud nemá žádné požadované vlastnosti kromě primárního klíče a všechny vlastnosti jsou null.

Omezení rizik

Pokud má váš model tabulku, která je závislá na všech volitelných sloupcích, ale očekává se, že navigace na ni nebude null , měla by být aplikace upravena tak, aby zpracovávala případy, kdy je nullnavigace . Pokud to není možné, měla by být požadovaná vlastnost přidána do typu entity nebo alespoň jedna vlastnost by měla mít přiřazenou jinounull hodnotu než hodnotu.

Všechny entity sdílející tabulku se sloupcem tokenu souběžnosti musí namapovat na vlastnost.

Problém se sledováním č. 14154

Staré chování

Podívejte se například na následující 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");
}

Před EF Core 3.0, pokud OrderDetails je vlastníkem nebo explicitně namapován Order na stejnou tabulku, aktualizace pouze OrderDetails neaktualizuje Version hodnotu v klientovi a další aktualizace se nezdaří.

Nové chování

Od verze 3.0 EF Core rozšíří novou Version hodnotu, pokud Order vlastní OrderDetails. V opačném případě se při ověřování modelu vyvolá výjimka.

Proč

Tato změna se změnila tak, aby se zabránilo zastaralé hodnotě tokenu souběžnosti, když se aktualizuje pouze jedna z entit mapovaných na stejnou tabulku.

Omezení rizik

Všechny entity sdílející tabulku musí obsahovat vlastnost, která je namapovaná na sloupec tokenu souběžnosti. Je možné, že se vytvoří ve stínovém stavu:

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

Vlastněné entity nelze dotazovat bez vlastníka pomocí sledovacího dotazu.

Problém se sledováním č. 18876

Staré chování

Před EF Core 3.0 může být vlastněné entity dotazovány jako jakákoli jiná navigace.

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

Nové chování

Od verze 3.0 se EF Core vyvolá, pokud sledovací dotaz projektuje vlastněnou entitu bez vlastníka.

Proč

Vlastněné entity nelze manipulovat bez vlastníka, takže v obrovské většině případů je dotazování tímto způsobem chyba.

Omezení rizik

Pokud by měla být vlastněná entita sledována tak, aby byla upravena jakýmkoli způsobem později, měl by být vlastník zahrnut do dotazu.

Jinak přidejte AsNoTracking() volání:

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

Zděděné vlastnosti z nemapovaných typů se teď mapují na jeden sloupec pro všechny odvozené typy.

Problém se sledováním č. 13998

Staré chování

Podívejte se například na následující 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>();
}

Před EF Core 3.0 ShippingAddress by vlastnost byla mapována na samostatné sloupce pro BulkOrder a Order ve výchozím nastavení.

Nové chování

Od verze 3.0 EF Core vytvoří pouze jeden sloupec pro ShippingAddress.

Proč

Starý behavoir byl neočekávaný.

Omezení rizik

Vlastnost je stále možné explicitně mapovat na samostatný sloupec u odvozených typů:

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");
}

Konvence vlastností cizího klíče už neodpovídá stejnému názvu jako hlavní vlastnost.

Problém se sledováním č. 13274

Staré chování

Podívejte se například na následující 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; }
}

Před EF Core 3.0 by se CustomerId vlastnost použila pro cizí klíč podle konvence. Pokud Order je ale vlastněný typ, stane se tím také CustomerId primární klíč a obvykle to není očekávání.

Nové chování

Od verze 3.0 se EF Core nepokouší používat vlastnosti cizích klíčů podle konvence, pokud mají stejný název jako hlavní vlastnost. Název hlavního typu zřetězený s názvem hlavní vlastnosti a název navigace zřetězený se vzory názvu hlavní vlastnosti se stále shodují. Příklad:

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; }
}

Proč

Tato změna byla provedena, aby se zabránilo chybnému definování vlastnosti primárního klíče ve vlastním typu.

Omezení rizik

Pokud byla vlastnost určena jako cizí klíč, a proto je součástí primárního klíče, explicitně ji nakonfigurujte jako takový.

Připojení k databázi je nyní zavřené, pokud se už nepoužívá před dokončením TransactionScope.

Problém se sledováním č. 14218

Staré chování

Před EF Core 3.0, pokud kontext otevře připojení uvnitř TransactionScope, připojení zůstane otevřené, zatímco aktuální TransactionScope je aktivní.

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();
    }
}

Nové chování

Od verze 3.0 EF Core připojení zavře hned po jeho použití.

Proč

Tato změna umožňuje použít více kontextů ve stejném TransactionScope. Nové chování také odpovídá EF6.

Omezení rizik

Pokud připojení musí zůstat otevřené explicitní volání OpenConnection() , aby se zajistilo, že EF Core ho předčasně nezavře:

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ždá vlastnost používá nezávislé generování celočíselného klíče v paměti.

Problém se sledováním č. 6872

Staré chování

Před EF Core 3.0 se pro všechny vlastnosti celočíselného klíče v paměti použil jeden generátor sdílených hodnot.

Nové chování

Od EF Core 3.0 získá každá celočíselná klíč vlastnost vlastní generátor hodnot při použití databáze v paměti. Pokud je databáze odstraněna, generování klíčů se resetuje pro všechny tabulky.

Proč

Tato změna byla provedena tak, aby se generování klíčů v paměti lépe srovnalo s generováním skutečných klíčů databáze a zlepšila schopnost izolovat testy od sebe při použití databáze v paměti.

Omezení rizik

To může narušit aplikaci, která spoléhá na konkrétní hodnoty klíče v paměti, které se mají nastavit. Zvažte místo toho, že se nespoléháte na konkrétní hodnoty klíče nebo aktualizujete tak, aby odpovídaly novému chování.

Backing fields are used by default

Problém se sledováním č. 12430

Staré chování

Před 3.0, i když bylo pole backing vlastnosti známé, EF Core by ve výchozím nastavení číst a zapisovat hodnotu vlastnosti pomocí metody getter a setter. Výjimkou bylo spuštění dotazu, kdy by se backingové pole nastavilo přímo, pokud je známo.

Nové chování

Od EF Core 3.0 platí, že pokud je známé záložní pole pro vlastnost, EF Core bude tuto vlastnost vždy číst a zapisovat pomocí backingového pole. To může způsobit přerušení aplikace, pokud aplikace spoléhá na další chování kódované do metody getter nebo setter.

Proč

Tato změna byla provedena, aby ef Core při provádění databázových operací zahrnujících entity ve výchozím nastavení chybně aktivovala obchodní logiku.

Omezení rizik

Chování před 3.0 lze obnovit prostřednictvím konfigurace režimu přístupu vlastnosti na ModelBuilder. Příklad:

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);

Vyvolání, pokud se najde více kompatibilních záložních polí

Problém se sledováním č. 12523

Staré chování

Před EF Core 3.0, pokud více polí odpovídalo pravidlu pro vyhledání záložního pole vlastnosti, pak by bylo jedno pole zvoleno na základě nějakého pořadí priority. To může způsobit použití nesprávného pole v nejednoznačnýchpřípadechch

Nové chování

Od EF Core 3.0 platí, že pokud se více polí shoduje se stejnou vlastností, vyvolá se výjimka.

Proč

Tato změna byla provedena, aby se zabránilo bezobslužné použití jednoho pole nad druhým, pokud je možné opravit pouze jedno pole.

Omezení rizik

Vlastnosti s nejednoznačnými backingovými poli musí mít pole, které se má použít explicitně. Například pomocí rozhraní API fluent:

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

Názvy vlastností jen pro pole by se měly shodovat s názvem pole.

Staré chování

Před EF Core 3.0 může být vlastnost určena řetězcovou hodnotou a pokud nebyla nalezena žádná vlastnost s tímto názvem v typu .NET, ef Core by se pokusila shodovat s polem pomocí pravidel konvence.

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

Nové chování

Počínaje EF Core 3.0 musí vlastnost jen pro pole přesně odpovídat názvu pole.

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

Proč

Tato změna byla provedena, aby se zabránilo použití stejného pole pro dvě vlastnosti pojmenované podobně, také vytvoří odpovídající pravidla pro vlastnosti jen pro pole stejné jako pro vlastnosti mapované na vlastnosti CLR.

Omezení rizik

Vlastnosti pouze pro pole musí být pojmenovány stejně jako pole, na které jsou mapovány. V budoucí verzi EF Core po verzi 3.0 plánujeme explicitně nakonfigurovat název pole, který se liší od názvu vlastnosti (viz problém č. 15307):

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

AddDbContext/AddDbContextPool už nevolá AddLogging a AddMemoryCache

Problém se sledováním č. 14756

Staré chování

Před EF Core 3.0, volání AddDbContext nebo AddDbContextPool by také zaregistrovat protokolování a ukládání paměti do mezipaměti služby DI prostřednictvím volání AddLogging a AddMemoryCache.

Nové chování

Od EF Core 3.0 AddDbContextAddDbContextPool už tyto služby nezaregistrujete pomocí injektáže závislostí (DI).

Proč

EF Core 3.0 nevyžaduje, aby tyto služby byly v kontejneru DI aplikace. Pokud ILoggerFactory je ale zaregistrovaný v kontejneru DI aplikace, bude ho stále používat EF Core.

Omezení rizik

Pokud vaše aplikace tyto služby potřebuje, zaregistrujte je explicitně v kontejneru DI pomocí AddLogging nebo AddMemoryCache.

AddEntityFramework* přidá IMemoryCache s limitem velikosti.

Sledování problému č. 12905

Staré chování

Před EF Core 3.0 by volání AddEntityFramework* metod také registrovalo služby ukládání paměti do mezipaměti s DI bez omezení velikosti.

Nové chování

Od EF Core 3.0 AddEntityFramework* zaregistruje službu IMemoryCache s limitem velikosti. Pokud některé další služby přidané později závisí na IMemoryCache, můžou rychle dosáhnout výchozího limitu, což způsobuje výjimky nebo snížený výkon.

Proč

Použití IMemoryCache bez omezení může vést k nečekanému využití paměti, pokud dojde k chybě v logice ukládání dotazů do mezipaměti nebo se dotazy generují dynamicky. Pokud máte výchozí limit, zmírní se potenciální útok DoS.

Omezení rizik

Ve většině případů AddEntityFramework* volání není nutné, pokud AddDbContext nebo AddDbContextPool je volána také. Nejlepším řešením je proto volání odebrat AddEntityFramework* .

Pokud vaše aplikace tyto služby potřebuje, zaregistrujte implementaci IMemoryCache explicitně s kontejnerem DI předem pomocí AddMemoryCache.

DbContext.Entry teď provádí místní detektivy DetectChanges.

Problém se sledováním č. 13552

Staré chování

Před EF Core 3.0 by volání DbContext.Entry způsobilo zjištění změn pro všechny sledované entity. Tím se zajistilo, že stav vystavený v EntityEntry aktuálním stavu.

Nové chování

Od EF Core 3.0 se teď volání DbContext.Entry pokusí detekovat změny v dané entitě a všechny sledované hlavní entity, které s ní souvisejí. To znamená, že změny jinde nemusí být zjištěny voláním této metody, což může mít vliv na stav aplikace.

Všimněte si, že pokud ChangeTracker.AutoDetectChangesEnabled je nastavena na false tuto místní detekci změn, bude zakázána.

Jiné metody, které způsobují detekci změn, například ChangeTracker.Entries a SaveChanges--stále způsobují plný DetectChanges všech sledovaných entit.

Proč

Tato změna byla provedena, aby se zlepšil výchozí výkon použití context.Entry.

Omezení rizik

Před voláním Entry zavolejte ChangeTracker.DetectChanges() explicitně, abyste zajistili chování před 3.0.

Klíče pole řetězců a bajtů nejsou ve výchozím nastavení generovány klientem.

Problém se sledováním č. 14617

Staré chování

Před ef Core 3.0 string a byte[] vlastnosti klíče lze použít bez explicitního nastavení hodnoty, která není null. V takovém případě by se hodnota klíče vygenerovala v klientovi jako identifikátor GUID serializovaný na bajty pro byte[].

Nové chování

Od EF Core 3.0 se vyvolá výjimka, která značí, že nebyla nastavena žádná hodnota klíče.

Proč

Tato změna byla provedena, protože hodnoty generované string/byte[] klientem obecně nejsou užitečné a výchozí chování ho ztěžovalo zdůvodnění generovaných hodnot klíčů běžným způsobem.

Omezení rizik

Chování před 3.0 lze získat explicitně zadáním, že vlastnosti klíče by měly používat vygenerované hodnoty, pokud není nastavena žádná jiná hodnota, která není null. Například s rozhraním API fluent:

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

Nebo s datovými poznámkami:

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

ILoggerFactory je teď vymezená služba

Problém se sledováním č. 14698

Staré chování

Před EF Core 3.0 ILoggerFactory byla zaregistrována jako jednoúčelová služba.

Nové chování

Od EF Core 3.0 ILoggerFactory je teď zaregistrovaný jako vymezený.

Proč

Tato změna byla provedena tak, aby umožňovala přidružení protokolovacího nástroje k DbContext instanci, která umožňuje další funkce a odstraňuje některé případy patologického chování, jako je explozi interních poskytovatelů služeb.

Omezení rizik

Tato změna by neměla mít vliv na kód aplikace, pokud se neregistruje a nepoužívá vlastní služby u interního poskytovatele služeb EF Core. To není běžné. V těchto případech bude většina věcí stále fungovat, ale každá jednoúčelová služba, která byla v závislosti na ILoggerFactory tom, bude nutné změnit, aby získala ILoggerFactory jiný způsob.

Pokud narazíte na podobné situace, zapište problém na sledování problémů EF Core Na GitHubu, abychom nám dali vědět, jak používáte ILoggerFactory , abychom lépe pochopili, jak to v budoucnu přerušit.

Opožděné načítání proxy serverů už nepředpokládá, že jsou plně načteny navigační vlastnosti.

Problém se sledováním č. 12780

Staré chování

Před EF Core 3.0, jakmile DbContext byl uvolněn, nebyl žádný způsob, jak zjistit, zda daná navigační vlastnost entity získané z tohoto kontextu byla plně načtena nebo nebyla. Proxy servery by místo toho předpokládaly, že se načte referenční navigace, pokud má nenulovou hodnotu a že se načte navigace kolekce, pokud není prázdná. V těchto případech by pokus o opožděné načtení byl no-op.

Nové chování

Počínaje ef Core 3.0 sledují proxy servery, jestli se načítá nebo ne navigační vlastnost. To znamená, že pokus o přístup k navigační vlastnosti načtené po vyřazení kontextu bude vždy bez operace, i když je načtená navigace prázdná nebo null. Naopak pokus o přístup k navigační vlastnosti, která není načtena, vyvolá výjimku, pokud je kontext uvolněn, i když navigační vlastnost je neprázdná kolekce. Pokud k této situaci dojde, znamená to, že se kód aplikace pokouší použít opožděné načítání v neplatné době a aplikace by se měla změnit tak, aby to neudělala.

Proč

Tato změna byla provedena tak, aby chování bylo konzistentní a správné při pokusu o opožděné načtení u odstraněné DbContext instance.

Omezení rizik

Aktualizujte kód aplikace tak, aby se nepokoušal líné načítání s uvolněným kontextem, nebo ho nakonfigurujte tak, aby se jedná o no-op, jak je popsáno ve zprávě o výjimce.

Nadměrné vytváření interních poskytovatelů služeb je teď ve výchozím nastavení chybou.

Problém se sledováním č. 10236

Staré chování

Před EF Core 3.0 se zaprotokoluje upozornění pro aplikaci, která vytváří patologický počet interních poskytovatelů služeb.

Nové chování

Od EF Core 3.0 se teď toto upozornění považuje za chybu a vyvolá se výjimka.

Proč

Tato změna byla provedena tak, aby řídila lepší kód aplikace prostřednictvím explicitnějšího zveřejnění tohoto patologického případu.

Omezení rizik

Nejvhodnější příčinou akce při výskytu této chyby je pochopení původní příčiny a zastavení vytváření tolik interních poskytovatelů služeb. Tuto chybu však lze převést zpět na upozornění (nebo ignorovat) prostřednictvím konfigurace v DbContextOptionsBuilderrozhraní . Příklad:

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

Nové chování pro HasOne/HasMany volaný jedním řetězcem

Problém se sledováním č. 9171

Staré chování

Před EF Core 3.0 byl kód volání HasOne nebo HasMany s jedním řetězcem interpretován matoucím způsobem. Příklad:

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

Kód vypadá, že se vztahuje Samurai k některému jinému typu entity pomocí Entrance navigační vlastnosti, která může být soukromá.

Ve skutečnosti se tento kód pokusí vytvořit relaci s určitým typem entity volaným Entrance bez navigační vlastnosti.

Nové chování

Počínaje EF Core 3.0 teď výše uvedený kód dělá to, co vypadalo, jako by to mělo být předtím.

Proč

Staré chování bylo velmi matoucí, zejména při čtení konfiguračního kódu a hledání chyb.

Omezení rizik

Tím se přeruší jenom aplikace, které explicitně konfigurují relace pomocí řetězců pro názvy typů a bez explicitního zadání navigační vlastnosti. To není běžné. Předchozí chování lze získat explicitně předáním null názvu navigační vlastnosti. Příklad:

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

Návratový typ pro několik asynchronních metod byl změněn z Task na ValueTask.

Problém se sledováním č. 15184

Staré chování

Následující asynchronní metody dříve vrátily Task<T>:

  • DbContext.FindAsync()
  • DbSet.FindAsync()
  • DbContext.AddAsync()
  • DbSet.AddAsync()
  • ValueGenerator.NextValueAsync() (a odvozené třídy)

Nové chování

Výše uvedené metody nyní vrací ValueTask<T> více než T předtím.

Proč

Tato změna snižuje počet přidělení haldy vzniklé při vyvolání těchto metod, což zlepšuje obecný výkon.

Omezení rizik

Aplikace jednoduše čekají na výše uvedená rozhraní API pouze je potřeba znovu zkompilovat – nejsou potřeba žádné zdrojové změny. Složitější použití (např. předání vrácené TaskTask.WhenAny()hodnoty) obvykle vyžaduje, aby vrácená ValueTask<T> hodnota byla převedena na volání AsTask() na niTask<T>. Všimněte si, že tím se neguje snížení přidělení, které tato změna přináší.

Relační poznámka:TypeMapping je teď jenom TypeMapping.

Problém se sledováním č. 9913

Staré chování

Název poznámky pro mapování typů byl "Relational:TypeMapping".

Nové chování

Název poznámky pro mapování typů je teď "TypeMapping".

Proč

Mapování typů se teď používají pro více než jen pro zprostředkovatele relačních databází.

Omezení rizik

Tím se aplikace, které přistupující k mapování typu dostanou přímo jako poznámka, což není běžné. Nejvhodnější akcí k opravě je použití rozhraní API pro přístup k mapování typů místo přímého použití poznámek.

ToTable pro odvozený typ vyvolá výjimku

Sledování problému č. 11811

Staré chování

Před EF Core 3.0, volaný na odvozený typ by byl ignorován, ToTable() protože pouze strategie mapování dědičnosti byla TPH, kde to není platné.

Nové chování

Počínaje EF Core 3.0 a v přípravě na přidání podpory TPT a TPC v pozdější verzi, ToTable() volané na odvozený typ teď vyvolá výjimku, aby se zabránilo neočekávané změně mapování v budoucnu.

Proč

V současné době není platné namapovat odvozený typ na jinou tabulku. Tato změna zabraňuje přerušení v budoucnu, když se stane platnou věcí.

Omezení rizik

Odeberte všechny pokusy o mapování odvozených typů na jiné tabulky.

ForSqlServerHasIndex nahrazený hasIndex

Problém se sledováním č. 12366

Staré chování

Před EF Core 3.0 poskytuje ForSqlServerHasIndex().ForSqlServerInclude() způsob konfigurace sloupců používaných s INCLUDE.

Nové chování

Od EF Core 3.0 se teď použití Include indexu podporuje na relační úrovni. Použijte HasIndex().ForSqlServerInclude().

Proč

Tato změna byla provedena kvůli konsolidaci rozhraní API pro indexy do Include jednoho místa pro všechny poskytovatele databáze.

Omezení rizik

Použijte nové rozhraní API, jak je znázorněno výše.

Změny rozhraní API metadat

Problém se sledováním č. 214

Nové chování

Následující vlastnosti byly převedeny na rozšiřující metody:

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

Proč

Tato změna zjednodušuje implementaci výše uvedených rozhraní.

Omezení rizik

Použijte nové metody rozšíření.

Změny rozhraní API metadat specifických pro zprostředkovatele

Problém se sledováním č. 214

Nové chování

Metody rozšíření specifické pro poskytovatele budou zploštěné:

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

Proč

Tato změna zjednodušuje implementaci výše uvedených rozšiřujících metod.

Omezení rizik

Použijte nové metody rozšíření.

EF Core už neodesílá direktivu pragma pro vynucení FK SQLite

Sledování problému č. 12151

Staré chování

Před EF Core 3.0 by EF Core odeslal PRAGMA foreign_keys = 1 při otevření připojení k SQLite.

Nové chování

Od EF Core 3.0 už EF Core neodesílá PRAGMA foreign_keys = 1 , když se otevře připojení k SQLite.

Proč

Tato změna byla provedena, protože EF Core ve výchozím nastavení používá SQLitePCLRaw.bundle_e_sqlite3 , což znamená, že vynucení FK je ve výchozím nastavení zapnuté a nemusí být explicitně povolené při každém otevření připojení.

Omezení rizik

Cizí klíče jsou ve výchozím nastavení povolené v SQLitePCLRaw.bundle_e_sqlite3, které se ve výchozím nastavení používají pro EF Core. V jiných případech je možné cizí klíče povolit zadáním Foreign Keys=True v připojovací řetězec.

Microsoft.EntityFrameworkCore.Sqlite teď závisí na SQLitePCLRaw.bundle_e_sqlite3

Staré chování

Před EF Core 3.0, EF Core použil SQLitePCLRaw.bundle_green.

Nové chování

Od EF Core 3.0 používá SQLitePCLRaw.bundle_e_sqlite3EF Core .

Proč

Tato změna byla provedena tak, aby verze SQLite používaná v iOSu byla konzistentní s jinými platformami.

Omezení rizik

Pokud chcete použít nativní verzi SQLite v iOSu, nakonfigurujte Microsoft.Data.Sqlite použití jiné SQLitePCLRaw sady.

Hodnoty GUID se teď ukládají jako TEXT na SQLite.

Problém se sledováním č. 15078

Staré chování

Hodnoty GUID byly dříve uloženy jako hodnoty objektů blob v SQLite.

Nové chování

Hodnoty GUID jsou nyní uloženy jako TEXT.

Proč

Binární formát identifikátorů GUID není standardizovaný. Uložením hodnot ve formátu TEXT je databáze kompatibilní s jinými technologiemi.

Omezení rizik

Existující databáze můžete migrovat do nového formátu spuštěním sql, jako je následující.

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';

V EF Core můžete také pokračovat v používání předchozího chování konfigurací převaděče hodnot pro tyto vlastnosti.

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

Microsoft.Data.Sqlite zůstává schopen číst hodnoty GUID ze sloupců BLOB i TEXT; Vzhledem k tomu, že se ale výchozí formát parametrů a konstant změnil, budete pravděpodobně muset provést akci pro většinu scénářů zahrnujících identifikátory GUID.

Hodnoty znaků se teď ukládají jako TEXT na SQLite.

Sledování problému č. 15020

Staré chování

Hodnoty znaku byly dříve bolely jako hodnoty INTEGER na SQLite. Například hodnota znaku A byla uložena jako celočíselná hodnota 65.

Nové chování

Hodnoty znaků se teď ukládají jako TEXT.

Proč

Ukládání hodnot jako text je přirozenější a databáze bude kompatibilita s jinými technologiemi.

Omezení rizik

Existující databáze můžete migrovat do nového formátu spuštěním sql, jako je následující.

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

V EF Core můžete také pokračovat v používání předchozího chování konfigurací převaděče hodnot pro tyto vlastnosti.

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

Microsoft.Data.Sqlite také dokáže číst hodnoty znaků ze sloupců INTEGER i TEXT, takže některé scénáře nemusí vyžadovat žádnou akci.

ID migrace se teď generují pomocí kalendáře invariantní jazykové verze.

Problém se sledováním č. 12978

Staré chování

ID migrace se neúmyslně vygenerovala pomocí kalendáře aktuální jazykové verze.

Nové chování

ID migrace se teď vždy generují pomocí kalendáře invariantní jazykové verze (Gregoriánský).

Proč

Pořadí migrací je důležité při aktualizaci databáze nebo řešení konfliktů při slučování. Použití invariantního kalendáře zabraňuje problémům s řazením, které můžou mít za následek, že členové týmu mají různé systémové kalendáře.

Omezení rizik

Tato změna ovlivní každého, kdo používá negregoriánský kalendář, ve kterém je rok větší než Gregoriánský kalendář (například thajský buddhistický kalendář). Stávající ID migrace bude potřeba aktualizovat, aby se nové migrace po existujících migracích objednávaly.

ID migrace najdete v atributu Migrace v souborech návrháře migrace.

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

Je také potřeba aktualizovat tabulku historie migrací.

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

PoužitíRowNumberForPaging bylo odebráno.

Sledování problému č. 16400

Staré chování

Před EF Core 3.0 UseRowNumberForPaging je možné použít k vygenerování SQL pro stránkování, které je kompatibilní s SQL Serverem 2008.

Nové chování

Od EF Core 3.0 ef vygeneruje EF pouze SQL pro stránkování, která je kompatibilní pouze s novějšími verzemi SQL Serveru.

Proč

Tuto změnu provádíme, protože SQL Server 2008 už není podporovaným produktem a aktualizuje tuto funkci tak, aby fungovala se změnami dotazů provedenými v EF Core 3.0, je důležitá práce.

Omezení rizik

Doporučujeme aktualizovat na novější verzi SQL Serveru nebo použít vyšší úroveň kompatibility, aby byl vygenerovaný SQL podporovaný. To znamená, že pokud to nemůžete udělat, pak okomentujte problém se sledováním s podrobnostmi. Toto rozhodnutí můžeme znovu navštívit na základě zpětné vazby.

Informace o rozšíření a metadata byly odebrány z IDbContextOptionsExtension

Problém se sledováním č. 16119

Staré chování

IDbContextOptionsExtension obsažené metody pro poskytování metadat o rozšíření.

Nové chování

Tyto metody byly přesunuty do nové DbContextOptionsExtensionInfo abstraktní základní třídy, která je vrácena z nové IDbContextOptionsExtension.Info vlastnosti.

Proč

Ve verzích od 2.0 do 3.0 jsme museli tyto metody několikrát přidat nebo změnit. Když je rozdělíte do nové abstraktní základní třídy, usnadníte si provádění těchto změn bez přerušení stávajících rozšíření.

Omezení rizik

Aktualizujte rozšíření tak, aby sledovala nový vzor. Příklady najdete v mnoha implementacích IDbContextOptionsExtension různých typů rozšíření ve zdrojovém kódu EF Core.

LogQueryPossibleExceptionWithAggregateOperator byl přejmenován.

Sledování problému č. 10985

Změnit

RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator byl přejmenován na RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning.

Proč

Zarovná pojmenování této události upozornění se všemi ostatními událostmi upozornění.

Omezení rizik

Použijte nový název. (Všimněte si, že se číslo ID události nezměnilo.)

Objasnění názvů omezení cizího klíče rozhraní API

Sledování problému č. 10730

Staré chování

Před EF Core 3.0 byly názvy omezení cizího klíče označovány jako "název". Příklad:

var constraintName = myForeignKey.Name;

Nové chování

Od EF Core 3.0 se teď názvy omezení cizího klíče označují jako "název omezení". Příklad:

var constraintName = myForeignKey.ConstraintName;

Proč

Tato změna přináší konzistenci pro pojmenování v této oblasti a také vysvětluje, že se jedná o název omezení cizího klíče, nikoli název sloupce nebo vlastnosti, na které je cizí klíč definován.

Omezení rizik

Použijte nový název.

IRelationalDatabaseCreator.HasTables/HasTablesAsync byly veřejně zpřístupněny

Problém se sledováním č. 15997

Staré chování

Před EF Core 3.0 byly tyto metody chráněny.

Nové chování

Od EF Core 3.0 jsou tyto metody veřejné.

Proč

Ef tyto metody používá k určení, jestli je databáze vytvořená, ale prázdná. To může být užitečné také z externího ef při určování, jestli se mají migrace použít nebo ne.

Omezení rizik

Změňte přístupnost všech přepsání.

Microsoft.EntityFrameworkCore.Design je teď balíček DevelopmentDependency

Sledování problému č. 11506

Staré chování

Před EF Core 3.0 byl Microsoft.EntityFrameworkCore.Design běžným balíčkem NuGet, jehož sestavení by bylo možné odkazovat na projekty, které na něm závisely.

Nové chování

Od EF Core 3.0 se jedná o balíček DevelopmentDependency. To znamená, že závislost nebude přechodně přetékat do jiných projektů a že už ve výchozím nastavení nemůžete odkazovat na jeho sestavení.

Proč

Tento balíček je určen pouze k použití v době návrhu. Nasazené aplikace by na ni neměly odkazovat. Vytvoření balíčku DevelopmentDependency posiluje toto doporučení.

Omezení rizik

Pokud potřebujete odkazovat na tento balíček, abyste přepsali chování při návrhu EF Core, můžete aktualizovat metadata položky PackageReference v projektu.

<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>

Pokud se na balíček odkazuje tranzitivně prostřednictvím Microsoft.EntityFrameworkCore.Tools, budete muset do balíčku přidat explicitní PackageReference, aby se změnila jeho metadata. Takový explicitní odkaz musí být přidán do libovolného projektu, kde jsou potřebné typy z balíčku.

Aktualizace SQLitePCL.raw na verzi 2.0.0

Problém se sledováním č. 14824

Staré chování

Microsoft.EntityFrameworkCore.Sqlite dříve závisel na verzi 1.1.12 SQLitePCL.raw.

Nové chování

Aktualizovali jsme balíček tak, aby závisel na verzi 2.0.0.

Proč

Verze 2.0.0 SQLitePCL.raw cílí na .NET Standard 2.0. Dříve cílil na .NET Standard 1.1, který vyžadoval velké uzavření tranzitivních balíčků, aby fungovaly.

Omezení rizik

SQLitePCL.raw verze 2.0.0 obsahuje některé zásadní změny. Podrobnosti najdete v poznámkách k verzi.

NetTopologySuite byl aktualizován na verzi 2.0.0.

Problém se sledováním č. 14825

Staré chování

Prostorové balíčky dříve závisely na verzi 1.15.1 NetTopologySuite.

Nové chování

Aktualizovali jsme balíček tak, aby závisel na verzi 2.0.0.

Proč

Cílem verze 2.0.0 NetTopologySuite je řešit několik problémů s použitelností, ke kterým dochází u uživatelů EF Core.

Omezení rizik

NetTopologySuite verze 2.0.0 obsahuje některé zásadní změny. Podrobnosti najdete v poznámkách k verzi.

Microsoft.Data.SqlClient se používá místo System.Data.SqlClient.

Problém se sledováním č. 15636

Staré chování

Microsoft.EntityFrameworkCore.SqlServer dříve závisel na System.Data.SqlClient.

Nové chování

Aktualizovali jsme balíček tak, aby závisel na Microsoft.Data.SqlClient.

Proč

Microsoft.Data.SqlClient je stěžejním ovladačem pro přístup k datům pro SQL Server a System.Data.SqlClient se už nezaměřuje na vývoj. Některé důležité funkce, například Always Encrypted, jsou k dispozici pouze v Microsoft.Data.SqlClient.

Omezení rizik

Pokud váš kód využívá přímou závislost na System.Data.SqlClient, musíte ho změnit tak, aby odkazovat na Microsoft.Data.SqlClient; protože tyto dva balíčky udržují velmi vysoký stupeň kompatibility rozhraní API, mělo by se jednat pouze o jednoduchý balíček a změnu oboru názvů.

Je potřeba nakonfigurovat několik nejednoznačných vztahů odkazujících na sebe.

Problém se sledováním č. 13573

Staré chování

Typ entity s více jednosměrnými navigačními vlastnostmi odkazujícími na sebe a odpovídajícími sadami FK se nesprávně nakonfiguroval jako jedna relace. Příklad:

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; }
}

Nové chování

Tento scénář se teď zjistí v sestavení modelu a vyvolá se výjimka, která značí, že model je nejednoznačný.

Proč

Výsledný model byl nejednoznačný a v tomto případě bude pravděpodobně chybný.

Omezení rizik

Použijte úplnou konfiguraci relace. Příklad:

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

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

DbFunction.Schema má hodnotu null nebo prázdný řetězec konfiguruje, aby byl ve výchozím schématu modelu.

Problém se sledováním č. 12757

Staré chování

DbFunction nakonfigurovaný se schématem jako prázdný řetězec byl považován za předdefinovanou funkci bez schématu. Například následující kód namapuje DatePart funkci CLR na DATEPART integrovanou funkci na SqlServeru.

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

Nové chování

Všechna mapování DbFunction se považují za namapovaná na uživatelem definované funkce. Prázdná řetězcová hodnota by proto funkci umístila do výchozího schématu modelu. Což může být schéma nakonfigurované explicitně přes rozhraní API modelBuilder.HasDefaultSchema() fluent nebo dbo jinak.

Proč

Dříve prázdné schéma bylo způsob, jak tuto funkci považovat za integrovanou, ale tato logika je použitelná pouze pro SqlServer, kde integrované funkce nepatří do žádného schématu.

Omezení rizik

Nakonfigurujte překlad DbFunction ručně tak, aby ho namapovali na integrovanou funkci.

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

EF Core 3.0 cílí na .NET Standard 2.1 místo na vrácení .NET Standard 2.0

Problém se sledováním č. 15498

EF Core 3.0 cílí na .NET Standard 2.1, což je zásadní změna, která vylučuje aplikace .NET Framework. EF Core 3.1 vrátil toto a cílí na .NET Standard 2.0 znovu.

Provádění dotazů se protokoluje na úrovni ladění– Vráceno

Problém se sledováním č. 14523

Tuto změnu jsme vrátili, protože nová konfigurace v EF Core 3.0 umožňuje, aby aplikace určila úroveň protokolu pro každou událost. Pokud chcete například přepnout protokolování SQL na Debug, explicitně nakonfigurujte úroveň v OnConfiguring nebo AddDbContext:

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