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.
Shrnutí
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.
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 FromSqlRaw
ExecuteSqlRaw
a 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);
ExecuteSqlInterpolated
ExecuteSqlInterpolatedAsync
Slouží FromSqlInterpolated
k 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ů. Třeba tenhle 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;
Načítání souvisejících entit teď probíhá v jednom dotazu.
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 tohoModelBuilder.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 tohoDbSet<>
by se mělo použít.DbContext.Query<>()
- Místo tohoDbContext.Set<>()
by se mělo použít.IQueryTypeConfiguration<TQuery>
- Místo tohoIEntityTypeConfiguration<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 null
null
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é.
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é Order
instance 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 null
navigace . 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é chování bylo 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.
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 AddDbContext
AddDbContextPool
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.
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 DbContextOptionsBuilder
rozhraní .
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
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é Task
Task.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.
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
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
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
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
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_sqlite3
EF 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.
Staré chování
Hodnoty znaku byly dříve uloženy 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.
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.
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
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
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.
SQLitePCL.raw aktualizováno 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)));