Dela via


Icke-bakåtkompatibla ändringar som ingår i EF Core 3.x

Följande API- och beteendeändringar kan bryta befintliga program när de uppgraderas till 3.x. Ändringar som vi förväntar oss endast påverkar databasleverantörer dokumenteras under leverantörändringar.

Sammanfattning

Störande ändring Effekt
LINQ-frågor utvärderas inte längre på klienten Hög
EF Core-kommandoradsverktyget dotnet ef är inte längre en del av .NET Core SDK- Hög
DetectChanges respekterar butiksgenererade nyckelvärden Hög
FromSql, ExecuteSql och ExecuteSqlAsync har bytt namn Hög
Frågetyper konsolideras med entitetstyper Hög
Entity Framework Core ingår inte längre i det delade ASP.NET Core-ramverket Medium
Kaskadborttagningar sker nu omedelbart som standard Mellan
Ivrig inläsning av relaterade entiteter sker nu i en enda fråga Medium
DeleteBehavior.Restrict har renare semantik Medium
Konfigurations-API för relationer av egna typer har ändrats Medium
Varje egenskap använder oberoende minnesintern heltalsnyckelgenerering Medium
Frågor utan spårning utför inte längre identitetsmatchning Medium
Förändringar i Metadata-API Medium
Providerspecifika metadata-API-ändringar Medium
UseRowNumberForPaging har tagits bort Medium
FromSql-metod när den används med lagrad procedur kan inte sammansättas Mellan
FromSql-metoder kan bara anges på frågerötter Låg
Temporära nyckelvärden är inte längre inställda på entitetsinstanser Låg
Beroende entiteter som delar tabellen med huvudkontot är nu valfria Låg
Alla entiteter som delar en tabell med en samtidighetstokenkolumn måste mappa den till en egenskap Låg
Ägda entiteter kan inte förfrågas utan att inkludera ägaren i en spårningsfråga Låg
Ärvda egenskaper från ommappade typer mappas nu till en enda kolumn för alla härledda typer Låg
Egenskapskonventionen för extern nyckel matchar inte längre med samma namn som huvudegenskapen Låg
Database-anslutningen stängs nu om den inte används längre innan TransactionScope har slutförts Låg
Bakomliggande fält används som standard Låg
Kasta om flera kompatibla bakgrundsfält hittas Låg
Egenskapsnamn för endast fält ska matcha fältnamnet Låg
AddDbContext/AddDbContextPool anropar inte längre AddLogging och AddMemoryCache Låg
AddEntityFramework* lägger till IMemoryCache med en storleksgräns Låg
DbContext.Entry utför nu en lokal DetectChanges Låg
Sträng- och bytearraynycklar genereras inte av klienten som standard Låg
ILoggerFactory är nu en begränsad tjänst Låg
proxyservrar med lazy-loading förutsätter inte längre att navigeringsegenskaperna är helt inlästa Låg
Överdrivet skapande av interna tjänstleverantörer är nu ett fel som standard Låg
Nytt beteende för HasOne/HasMany anropas med en enda sträng Låg
Returtypen för flera asynkrona metoder har ändrats från Aktivitet till ValueTask Låg
Annoteringen Relational:TypeMapping är nu bara TypeMapping Låg
ToTable på en härledd typ utlöser ett undantag Låg
EF Core skickar inte längre pragma för SQLite FK-tillämpning Låg
Microsoft.EntityFrameworkCore.Sqlite är nu beroende av SQLitePCLRaw.bundle_e_sqlite3 Låg
Guid-värden lagras nu som TEXT på SQLite Låg
Char-värden lagras nu som TEXT på SQLite Låg
migrerings-ID:t genereras nu med hjälp av den invarianta kulturens kalender Låg
Tilläggsinformation/metadata har tagits bort från IDbContextOptionsExtension Låg
LogQueryPossibleExceptionWithAggregateOperator har bytt namn Låg
Klargöra API för namn på referensnyckelbegränsningar Låg
IRelationalDatabaseCreator.HasTables/HasTablesAsync har gjorts publika Låg
Microsoft.EntityFrameworkCore.Design är nu ett DevelopmentDependency-paket Låg
SQLitePCL.raw uppdaterad till version 2.0.0 Låg
NetTopologySuite uppdaterad till version 2.0.0 Låg
Microsoft.Data.SqlClient används i stället för System.Data.SqlClient Låg
Flera tvetydiga självrefererande relationer måste konfigureras Låg
När DbFunction.Schema är null eller en tom sträng, konfigureras det till att finnas i modellens standardschema Låg
EF Core 3.0 stödjer .NET Standard 2.1 i stället för .NET Standard 2.0 Återgått
Frågekörning loggas på felsökningsnivå återställd

Ändringar med hög påverkan

LINQ-frågor utvärderas inte längre på klienten

Spårningsproblem #14935Se även problem #12795

Gammalt beteende

Innan 3.0, när EF Core inte kunde konvertera ett uttryck som var en del av en fråga till antingen SQL eller en parameter, utvärderade det automatiskt uttrycket på klienten. Som standard utlöste klientutvärdering av potentiellt dyra uttryck bara en varning.

Nytt beteende

Från och med 3.0 tillåter EF Core endast att uttryck i projektionen på den översta nivån (det sista Select()-anropet i frågan) utvärderas på klienten. När uttryck i någon annan del av frågan inte kan konverteras till antingen SQL eller en parameter genereras ett undantag.

Varför

Med automatisk klientutvärdering av frågor kan många frågor köras även om viktiga delar av dem inte kan översättas. Det här beteendet kan leda till oväntat och potentiellt skadligt beteende som bara kan bli uppenbart i produktionen. Ett villkor i ett Where()-anrop som inte kan översättas kan till exempel göra att alla rader från tabellen överförs från databasservern och att filtret tillämpas på klienten. Den här situationen kan enkelt gå oupptäckt om tabellen bara innehåller några rader under utveckling, men slår hårt när programmet flyttas till produktion, där tabellen kan innehålla miljontals rader. Klientutvärderingsvarningar visade sig också vara för lätta att ignorera under utvecklingen.

Dessutom kan automatisk klientutvärdering leda till problem där förbättrad frågeöversättning för specifika uttryck orsakade oavsiktliga icke-bakåtkompatibla ändringar mellan versioner.

Åtgärder

Om en fråga inte kan översättas fullständigt skriver du antingen om frågan i ett formulär som kan översättas eller använder AsEnumerableAsync(), ToListAsync()eller liknande för att uttryckligen föra tillbaka data till klienten där den sedan kan bearbetas ytterligare med LINQ-to-Objects.

Ändringar med medelpåverkan

Entity Framework Core är inte längre en del av det delade ramverket för ASP.NET Core

Meddelanden om spårningsproblem #325

Gammalt beteende

Innan ASP.NET Core 3.0, när du lade till en paketreferens till Microsoft.AspNetCore.App eller Microsoft.AspNetCore.All, skulle den innehålla EF Core och några av EF Core-dataprovidrar som SQL Server-providern.

Nytt beteende

Från och med 3.0 innehåller det delade ASP.NET Core-ramverket inte EF Core eller några EF Core-dataproviders.

Varför

Innan den här ändringen krävdes olika steg för att skaffa EF Core beroende på om programmet riktade sig mot ASP.NET Core och SQL Server eller inte. Uppgradering av ASP.NET Core tvingade också till en uppgradering av EF Core och SQL Server-leverantören, vilket inte alltid är önskvärt.

Med den här ändringen är upplevelsen av att få EF Core densamma för alla leverantörer, .NET-implementeringar och programtyper som stöds. Utvecklare kan nu också styra exakt när EF Core- och EF Core-dataleverantörer uppgraderas.

Åtgärder

Om du vill använda EF Core i ett ASP.NET Core 3.0-program eller något annat program som stöds lägger du uttryckligen till en paketreferens till EF Core-databasprovidern som programmet ska använda.

EF Core-kommandoradsverktyget dotnet ef är inte längre en del av .NET Core SDK

spårningsproblem #14016

Gammalt beteende

Före 3.0 inkluderades verktyget dotnet ef i .NET Core SDK och var lätt att använda från kommandoraden från något projekt utan att kräva extra steg.

Nytt beteende

Från och med 3.0 innehåller .NET SDK inte verktyget dotnet ef, så innan du kan använda det måste du uttryckligen installera det som ett lokalt eller globalt verktyg.

Varför

Med den här ändringen kan vi distribuera och uppdatera dotnet ef som ett vanligt .NET CLI-verktyg på NuGet, vilket överensstämmer med det faktum att EF Core 3.0 också alltid distribueras som ett NuGet-paket.

Åtgärder

Om du vill kunna hantera migreringar eller skapa en DbContextinstallerar du dotnet-ef som ett globalt verktyg:

dotnet tool install --global dotnet-ef

Du kan också hämta ett lokalt verktyg när du återställer beroendena för ett projekt som deklarerar det som ett verktygsberoende med hjälp av en -verktygsmanifestfil.

Ändringar med låg påverkan

FromSql, ExecuteSql och ExecuteSqlAsync har bytt namn

spårningsproblem #10996

Viktig

ExecuteSqlCommand och ExecuteSqlCommandAsync är inaktuella. Använd dessa metoder i stället.

Gammalt beteende

Före EF Core 3.0 överbelastades dessa metodnamn för att fungera med antingen en normal sträng eller en sträng som ska interpoleras till SQL och parametrar.

Nytt beteende

Från och med EF Core 3.0 använder du FromSqlRaw, ExecuteSqlRawoch ExecuteSqlRawAsync för att skapa en parametriserad fråga där parametrarna skickas separat från frågesträngen. Till exempel:

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

Använd FromSqlInterpolated, ExecuteSqlInterpolatedoch ExecuteSqlInterpolatedAsync för att skapa en parametriserad fråga där parametrarna skickas som en del av en interpolerad frågesträng. Till exempel:

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

Observera att båda frågorna ovan skapar samma parameteriserade SQL med samma SQL-parametrar.

Varför

Metodöverlagringar som den här gör det mycket enkelt att av misstag anropa råsträngsmetoden när avsikten var att anropa den interpolerade strängmetoden och tvärtom. Detta kan leda till att frågor inte parametriseras när de borde ha varit det.

Åtgärder

Växla om du vill använda de nya metodnamnen.

FromSql-metoden kan inte komponeras när den används med en lagrad procedur

spårningsproblem #15392

Gammalt beteende

Innan EF Core 3.0 försökte "FromSql"-metoden identifiera om den överförda SQL:en kunde komponeras. Det genomförde en klientutvärdering när SQL var icke-sammansättbar, som en lagrad procedur. Följande fråga fungerade genom att köra den lagrade proceduren på servern och göra FirstOrDefault på klientsidan.

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

Nytt beteende

Från och med EF Core 3.0 försöker EF Core inte parsa SQL. Så om du skriver efter FromSqlRaw/FromSqlInterpolated kommer EF Core att komponera SQL genom att skapa en underfråga. Så om du använder en lagrad procedur med sammansättning får du ett undantag för ogiltig SQL-syntax.

Varför

EF Core 3.0 stöder inte automatisk klientutvärdering, eftersom det var felbenäget enligt beskrivningen här.

Åtgärder

Om du använder en lagrad procedur i FromSqlRaw/FromSqlInterpolated vet du att den inte kan skapas, så du kan lägga till AsEnumerable/AsAsyncEnumerable direkt efter FromSql-metodanropet för att undvika komposition på serversidan.

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

FromSql-metoder kan bara anges på frågerötter

spårningsproblem #15704

Gammalt beteende

Före EF Core 3.0 kan FromSql-metoden anges var som helst i frågan.

Nytt beteende

Från och med EF Core 3.0 kan de nya metoderna FromSqlRaw och FromSqlInterpolated (som ersätter FromSql) endast anges på frågerötter, d.v.s. direkt på DbSet<>. Om du försöker ange dem någon annanstans resulterar det i ett kompileringsfel.

Varför

Att ange FromSql någon annanstans än på en DbSet inte hade någon ytterligare betydelse eller mervärde och kan orsaka tvetydighet i vissa scenarier.

Åtgärder

FromSql-anrop bör flyttas så att de är direkt på den DbSet de gäller för.

Frågor utan spårning utför inte längre identitetsmatchning

spårningsproblem #13518

Gammalt beteende

Före EF Core 3.0 skulle samma entitetsinstans användas för varje förekomst av en entitet med en viss typ och ID. Detta matchar beteendet för spårning av sökfrågor. Till exempel den här frågan:

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

returnerar samma Category instans för varje Product som är associerad med den angivna kategorin.

Nytt beteende

Från och med EF Core 3.0 skapas olika entitetsinstanser när en entitet med en viss typ och ID påträffas på olika platser i den returnerade grafen. Frågan ovan returnerar till exempel nu en ny Category instans för varje Product även när två produkter är associerade med samma kategori.

Varför

Identitetsmatchning (dvs. att fastställa att en entitet har samma typ och ID som en tidigare påträffad entitet) ger ytterligare prestanda och minnesomkostnader. Detta går vanligtvis emot anledningen till varför frågor utan spårning används från början. Även om identitetsmatchning ibland kan vara användbar, behövs det inte om entiteterna ska serialiseras och skickas till en klient, vilket är vanligt för frågor utan spårning.

Åtgärder

Använd en spårningsfråga om identitetsmatchning krävs.

Temporära nyckelvärden anges inte längre till entitetsinstanser

spårningsproblem #12378

Gammalt beteende

Före EF Core 3.0 tilldelades tillfälliga värden till alla nyckelegenskaper som senare skulle ha ett verkligt värde som genererades av databasen. Vanligtvis var dessa temporära värden stora negativa tal.

Nytt beteende

Från och med 3.0 lagrar EF Core det tillfälliga nyckelvärdet som en del av entitetens spårningsinformation och lämnar själva nyckelegenskapen oförändrad.

Varför

Den här ändringen gjordes för att förhindra att tillfälliga nyckelvärden felaktigt blir permanenta när en entitet som tidigare har spårats av någon DbContext instans flyttas till en annan DbContext instans.

Åtgärder

Program som tilldelar primärnyckelvärden till externa nycklar för att bilda associationer mellan entiteter kan bero på det gamla beteendet om de primära nycklarna är butiksgenererade och tillhör entiteter i Added tillstånd. Detta kan undvikas genom att:

  • Använder inte butiksgenererade nycklar.
  • Ange navigeringsegenskaper för att upprätta relationer i stället för att ange värden för utländsk nyckel.
  • Hämta de faktiska temporära nyckelvärdena från entitetens spårningsinformation. Till exempel returnerar context.Entry(blog).Property(e => e.Id).CurrentValue det tillfälliga värdet även om blog.Id inte har angetts.

DetectChanges respekterar butiksgenererade nyckelvärden

spårningsproblem #14616

Gammalt beteende

Före EF Core 3.0 skulle en ospårad entitet som hittas av DetectChanges spåras i tillståndet Added och infogas som en ny rad när SaveChanges anropas.

Nytt beteende

Från och med EF Core 3.0, om en entitet använder genererade nyckelvärden och ett visst nyckelvärde anges, spåras entiteten i Modified tillstånd. Det innebär att en rad för entiteten antas finnas och uppdateras när SaveChanges anropas. Om nyckelvärdet inte har angetts, eller om entitetstypen inte använder genererade nycklar, spåras den nya entiteten fortfarande som Added som i tidigare versioner.

Varför

Den här ändringen gjordes för att göra det enklare och mer konsekvent att arbeta med frånkopplade entitetsdiagram när du använder butiksgenererade nycklar.

Åtgärder

Den här ändringen kan bryta ett program om en entitetstyp har konfigurerats för att använda genererade nycklar, men nyckelvärden anges uttryckligen för nya instanser. Korrigeringen är att uttryckligen konfigurera nyckelegenskaperna så att de inte använder genererade värden. Till exempel med api:et fluent:

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

Eller med dataanteckningar:

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

Kaskadborttagningar sker nu omedelbart som standard

spårningsproblem #10114

Gammalt beteende

Före 3.0 tillämpade EF Core sammanhängande åtgärder (ta bort beroende entiteter när ett obligatoriskt huvudnamn tas bort eller när relationen till ett obligatoriskt huvudnamn har brutits) inte förrän SaveChanges anropades.

Nytt beteende

Från och med 3.0 tillämpar EF Core sammanhängande åtgärder så snart utlösarvillkoret har identifierats. Om du till exempel anropar context.Remove() för att ta bort en huvudentitet kommer alla spårade relaterade nödvändiga beroenden också att ställas in på Deleted omedelbart.

Varför

Den här ändringen gjordes för att förbättra upplevelsen för databindnings- och granskningsscenarier där det är viktigt att förstå vilka entiteter som ska tas bort innanSaveChanges anropas.

Åtgärder

Det tidigare beteendet kan återställas via inställningarna på context.ChangeTracker. Till exempel:

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

spårningsproblem #18022

Gammalt beteende

Före 3.0 orsakade ivrig inläsning av samlingsnavigeringar via Include operatorer att flera frågor genererades på relationsdatabasen, en för varje relaterad entitetstyp.

Nytt beteende

Från och med 3.0 genererar EF Core en enda fråga med JOIN på relationsdatabaser.

Varför

Att skicka flera förfrågningar för att implementera en enda LINQ-fråga orsakade många problem, inklusive prestandaproblem eftersom flera databasanrop var nödvändiga, och problem med datakonsekvens eftersom varje begäran kunde observera ett annat tillstånd för databasen.

Åtgärder

Även om detta tekniskt sett inte är en bakåtkompatibel ändring kan det ha en betydande effekt på applikationens prestanda när en enskild fråga innehåller ett stort antal Include-operatorer vid samlingsnavigeringar. Se den här kommentaren för mer information och för att skriva om frågor på ett mer effektivt sätt.

**

DeleteBehavior.Restrict har renare semantik

spårningsproblem #12661

Gammalt beteende

Före 3.0 skapade DeleteBehavior.Restrict främmande nycklar i databasen med Restrict semantik, men ändrade även intern justering på ett otydligt sätt.

Nytt beteende

Från och med 3.0 ser DeleteBehavior.Restrict till att utländska nycklar skapas med Restrict semantik; det vill säga: inga kaskader; kastar ett undantag vid begränsningsöverträdelser, utan att påverka EF:s interna korrigering.

Varför

Denna ändring gjordes för att förbättra upplevelsen för att använda DeleteBehavior på ett intuitivt sätt, utan oväntade biverkningar.

Åtgärder

Det tidigare beteendet kan återställas med hjälp av DeleteBehavior.ClientNoAction.

Frågetyper konsolideras med entitetstyper

spårningsproblem #14194

Gammalt beteende

Före EF Core 3.0 var frågetyper ett sätt att fråga efter data som inte definierar en primärnyckel på ett strukturerat sätt. Det vill säga en frågetyp användes för att mappa entitetstyper utan nycklar (mer sannolikt från en vy, men eventuellt från en tabell) medan en vanlig entitetstyp användes när en nyckel var tillgänglig (mer sannolikt från en tabell, men möjligen från en vy).

Nytt beteende

En frågetyp blir nu bara en entitetstyp utan primärnyckel. Nyckellösa entitetstyper har samma funktioner som frågetyper i tidigare versioner.

Varför

Den här ändringen gjordes för att minska förvirringen kring syftet med frågetyper. Mer specifikt är de nyckellösa entitetstyper och de är i sig skrivskyddade på grund av detta, men de bör inte användas bara för att en entitetstyp måste vara skrivskyddad. På samma sätt mappas de ofta till vyer, men det beror bara på att vyer ofta inte definierar nycklar.

Åtgärder

Följande delar av API:et är nu föråldrade:

  • ModelBuilder.Query<>() – I stället måste ModelBuilder.Entity<>().HasNoKey() anropas för att markera en entitetstyp som saknar nycklar. Detta skulle fortfarande inte konfigureras enligt konventionen för att undvika felkonfiguration när en primärnyckel förväntas men inte följer konventionen.
  • DbQuery<> – I stället ska DbSet<> användas.
  • DbContext.Query<>() – I stället ska DbContext.Set<>() användas.
  • IQueryTypeConfiguration<TQuery> – I stället ska IEntityTypeConfiguration<TEntity> användas.

Note

På grund av ett problem i 3.x vid frågor mot nyckellösa entiteter som har alla egenskaper inställda på null returneras en null i stället för en entitet, om det här problemet gäller för ditt scenario lägger du också till logik för att hantera null i resultat.

Konfigurations-API för ägda typrelationer har ändrats

Spårningsproblem #12444Spårningsproblem #9148Spårningsproblem #14153

Gammalt beteende

Före EF Core 3.0 utfördes konfigurationen av den ägda relationen direkt efter OwnsOne- eller OwnsMany-anropet.

Nytt beteende

Från och med EF Core 3.0 finns det nu fluent API för att konfigurera en navigeringsegenskap för ägaren med hjälp av WithOwner(). Till exempel:

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

Konfigurationen som är relaterad till relationen mellan ägare och ägd bör nu kopplas efter WithOwner() på samma sätt som andra relationer konfigureras. Konfigurationen för den ägda typen skulle fortfarande vara länkad efter OwnsOne()/OwnsMany(). Till exempel:

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

Om du anropar Entity(), HasOne()eller Set() med ett mål av ägartyp utlöser du nu ett undantag.

Varför

Den här ändringen gjordes för att skapa en tydligare åtskillnad mellan att konfigurera själva den ägda typen och relationen till för den ägda typen. Detta i sin tur tar bort tvetydighet och förvirring kring metoder som HasForeignKey.

Åtgärder

Ändra konfigurationen av ägda typrelationer så att den nya API-ytan används enligt exemplet ovan.

Beroende entiteter som delar tabellen med huvudnamnet är nu valfria

spårningsproblem #9005

Gammalt beteende

Tänk på följande modell:

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

Om OrderDetails ägs av Order eller uttryckligen mappas till samma tabell innan EF Core 3.0 krävs alltid en OrderDetails instans när du lägger till en ny Order.

Nytt beteende

Från och med 3.0 kan EF Core lägga till en Order utan en OrderDetails och mappar alla OrderDetails-egenskaper förutom primärnyckeln till nullable kolumner. När du frågar i EF Core-uppsättningar, ställs OrderDetails till null om någon av dess nödvändiga egenskaper saknar ett värde, eller om den inte har några nödvändiga egenskaper förutom den primära nyckeln och alla egenskaper är null.

Åtgärder

Om din modell har en tabelldelning som är beroende av alla valfria kolumner, men navigeringen som pekar på den inte förväntas vara null bör programmet ändras för att hantera ärenden när navigeringen är null. Om detta inte är möjligt ska en obligatorisk egenskap läggas till i entitetstypen, eller så bör minst en egenskap ha ett icke-null värde som tilldelats den.

Alla entiteter som delar en tabell med en samtidighetstokenkolumn måste mappa den till en egenskap

spårningsproblem #14154

Gammalt beteende

Tänk på följande modell:

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

Innan EF Core 3.0, om OrderDetails ägs av Order eller uttryckligen mappas till samma tabell, kommer en uppdatering av endast OrderDetails inte att uppdatera Version-värdet på klienten och nästa uppdatering kommer att misslyckas.

Nytt beteende

Från och med 3.0 sprider EF Core det nya Version värdet till Order om det äger OrderDetails. Annars utlöses ett undantag under modellverifieringen.

Varför

Den här ändringen gjordes för att undvika ett inaktuellt samtidighetstokenvärde när endast en av entiteterna som mappats till samma tabell uppdateras.

Åtgärder

Alla entiteter som delar tabellen måste innehålla en egenskap som är mappad till kolumnen samtidighetstoken. Det är möjligt att skapa en i skuggtillstånd:

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

Ägda entiteter kan inte förfrågas utan att använda ägarens spårningsfråga

spårningsproblem #18876

Gammalt beteende

Före EF Core 3.0 kan ägda entiteter frågas efter som vilken annan navigering som helst.

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

Nytt beteende

Från och med 3.0 genererar EF Core om en spårningsfråga projicerar en ägd entitet utan ägaren.

Varför

Ägda entiteter kan inte manipuleras utan ägaren, så i de allra flesta fall är det ett fel att fråga dem på det här sättet.

Åtgärder

Om den ägda entiteten ska spåras för att ändras på något sätt senare bör ägaren inkluderas i frågan.

Lägg annars till ett AsNoTracking()-anrop:

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

Ärvda egenskaper från omappade typer mappas nu till en enda kolumn för alla härledda typer

spårningsproblem #13998

Gammalt beteende

Tänk på följande modell:

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

Före EF Core 3.0 mappas egenskapen ShippingAddress till separata kolumner för BulkOrder och Order som standard.

Nytt beteende

Från och med 3.0 skapar EF Core bara en kolumn för ShippingAddress.

Varför

Det gamla beteendet var oväntat.

Åtgärder

Egenskapen kan fortfarande mappas explicit till en separat kolumn för de härledda typerna:

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

Konventionen för utländska nycklar matchar inte längre samma namn som huvudegenskapen.

spårningsproblem #13274

Gammalt beteende

Tänk på följande modell:

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

Före EF Core 3.0 skulle egenskapen CustomerId användas för främmande nyckel enligt konventionen. Men om Order är en ägd typ skulle detta också göra CustomerId till den primära nyckeln, och detta är vanligtvis inte förväntningen.

Nytt beteende

Från och med 3.0 försöker EF Core inte använda egenskaper för främmande nycklar som standard om de har samma namn som huvudegenskapen. Huvudtypens namn som är sammanfogat med huvudegenskapens namn och navigeringsnamnet som är sammanfogat med huvudegenskapens namn matchar fortfarande mönstren. Till exempel:

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

Varför

Den här ändringen gjordes för att undvika att felaktigt definiera en primärnyckelegenskap för den ägda typen.

Åtgärder

Om egenskapen var avsedd att vara den utländska nyckeln och därmed en del av den primära nyckeln, bör du uttryckligen konfigurera den som sådan.

Databasanslutningen stängs nu om den inte används längre innan TransactionScope har slutförts

spårningsproblem #14218

Gammalt beteende

Om kontexten öppnar anslutningen i en TransactionScopeföre EF Core 3.0 förblir anslutningen öppen medan den aktuella TransactionScope är aktiv.

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

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

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

Nytt beteende

Från och med 3.0 stänger EF Core anslutningen så snart den har använts.

Varför

Med den här ändringen kan du använda flera kontexter i samma TransactionScope. Det nya beteendet matchar även EF6.

Förmildrande åtgärder

** Om anslutningen måste förbli öppen, genom att explicit anropa OpenConnection() ser man till att EF Core inte stänger den i förtid.

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

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

Varje egenskap använder oberoende minnesintern heltalsnyckelgenerering

spårningsproblem #6872

Gammalt beteende

Före EF Core 3.0 användes en delad värdegenerator för alla heltalsnyckelegenskaper i minnet.

Nytt beteende

Från och med EF Core 3.0 hämtar varje heltalsnyckelegenskap sin egen värdegenerator när du använder den minnesinterna databasen. Om databasen också tas bort återställs nyckelgenereringen för alla tabeller.

Varför

Den här ändringen gjordes för att justera minnesintern nyckelgenerering närmare till verklig databasnyckelgenerering och för att förbättra möjligheten att isolera tester från varandra när du använder minnesintern databas.

Åtgärder

Detta kan bryta ett program som förlitar sig på specifika minnesinterna nyckelvärden som ska anges. Överväg att i stället inte förlita dig på specifika nyckelvärden eller uppdatera för att matcha det nya beteendet.

Bakfält används som standard

spårningsproblem #12430

Gammalt beteende

Före 3.0, även om bakgrundsfältet för en egenskap var känt, skulle EF Core fortfarande som standard läsa och skriva egenskapsvärdet med hjälp av egenskaps getter- och setter-metoderna. Undantaget till detta var frågekörning, där bakgrundsfältet skulle anges direkt om det är känt.

Nytt beteende

Från och med EF Core 3.0, om bakgrundsfältet för en egenskap är känt, läser och skriver EF Core alltid egenskapen med hjälp av bakgrundsfältet. Detta kan orsaka en programbrytning om programmet förlitar sig på ytterligare beteende som kodas i metoden getter eller setter.

Varför

Den här ändringen gjordes för att förhindra att EF Core felaktigt utlöser affärslogik som standard när databasåtgärder som involverar entiteterna utförs.

Åtgärder

Beteendet före 3.0 kan återställas via konfigurationen av egenskapens åtkomstläge på ModelBuilder. Till exempel:

modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);

Kasta om flera kompatibla bakgrundsfält hittas

spårningsproblem #12523

Gammalt beteende

Om flera fält matchade reglerna för att hitta bakgrundsfältet för en egenskap före EF Core 3.0 skulle ett fält väljas baserat på någon prioritetsordning. Detta kan göra att fel fält används i tvetydiga fall.

Nytt beteende

Från och med EF Core 3.0 genereras ett undantag om flera fält matchas med samma egenskap.

Varför

Den här ändringen gjordes för att undvika tyst användning av ett fält över ett annat när endast ett kan vara korrekt.

Åtgärder

Egenskaper med tvetydiga bakgrundsfält måste ha det fält som ska användas uttryckligen. Du kan till exempel använda API:et fluent:

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

Namn på endast fältegenskaper ska matcha fältnamnet

Gammalt beteende

Före EF Core 3.0 kunde en egenskap anges med ett strängvärde och om ingen egenskap med det namnet hittades på .NET-typen skulle EF Core försöka matcha den med ett fält med hjälp av konventionsregler.

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

Nytt beteende

Från och med EF Core 3.0 måste en endast fältegenskap matcha fältnamnet exakt.

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

Varför

Den här ändringen gjordes för att undvika att använda samma fält för två egenskaper med namnet på samma sätt. Matchningsreglerna för endast fältegenskaper blir desamma som för egenskaper som mappas till CLR-egenskaper.

Åtgärder

Endast fältegenskaper måste namnges på samma sätt som det fält som de mappas till. I en framtida version av EF Core efter 3.0 planerar vi att återaktivera explicit konfiguration av ett fältnamn som skiljer sig från egenskapsnamnet (se problem #15307):

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

AddDbContext/AddDbContextPool anropar inte längre AddLogging och AddMemoryCache

spårningsproblem #14756

Gammalt beteende

Innan EF Core 3.0 skulle anrop till AddDbContext eller AddDbContextPool också registrera loggnings- och minnescachetjänster med DI via anrop till AddLogging och AddMemoryCache.

Nytt beteende

Från och med EF Core 3.0 kommer AddDbContext och AddDbContextPool inte längre att registrera dessa tjänster med beroendeinjektion (DI).

Varför

EF Core 3.0 kräver inte att dessa tjänster finns i programmets DI-container. Men om ILoggerFactory är registrerad i programmets DI-container används den fortfarande av EF Core.

Åtgärder

Om programmet behöver dessa tjänster registrerar du dem uttryckligen med DI-containern med hjälp av AddLogging eller AddMemoryCache.

AddEntityFramework* lägger till IMemoryCache med en storleksgräns

spårningsproblem #12905

Gammalt beteende

Innan EF Core 3.0 skulle anrop av AddEntityFramework* metoder också registrera cachelagringstjänster för minne med DI utan storleksgräns.

Nytt beteende

Från och med EF Core 3.0 registrerar AddEntityFramework* en IMemoryCache-tjänst med en storleksgräns. Om andra tjänster som läggs till efteråt är beroende av IMemoryCache kan de snabbt nå standardgränsen som orsakar undantag eller försämrad prestanda.

Varför

Om du använder IMemoryCache utan en gräns kan det leda till okontrollerad minnesanvändning om det finns en bugg i cachelagringslogik för frågor eller om frågorna genereras dynamiskt. Om du har en standardgräns minimeras en potentiell DoS-attack.

Åtgärder

I de flesta fall är det inte nödvändigt att anropa AddEntityFramework* om AddDbContext eller AddDbContextPool också anropas. Därför är den bästa lösningen att ta bort AddEntityFramework*-anropet.

Om programmet behöver dessa tjänster registrerar du en IMemoryCache-implementering explicit med DI-containern i förväg med hjälp av AddMemoryCache-.

DbContext.Entry utför nu en lokal ändringsdetektion

spårningsproblem #13552

Gammalt beteende

Innan EF Core 3.0 skulle ett anrop av DbContext.Entry resultera i att ändringar identifierades för alla spårade entiteter. Detta säkerställde att tillståndet som exponerades i EntityEntry var up-to-date.

Nytt beteende

Från och med EF Core 3.0 försöker anropa DbContext.Entry nu bara identifiera ändringar i den angivna entiteten och eventuella spårade huvudobjektentiteter som är relaterade till den. Det innebär att ändringar någon annanstans kanske inte har identifierats genom att anropa den här metoden, vilket kan påverka programtillståndet.

Observera att om ChangeTracker.AutoDetectChangesEnabled är inställt på false inaktiveras även den här lokala ändringsidentifieringen.

Andra metoder som orsakar ändringsdetektering – till exempel ChangeTracker.Entries och SaveChanges– orsakar fortfarande en fullständig DetectChanges för alla spårade entiteter.

Varför

Den här ändringen gjordes för att förbättra standardprestandan för att använda context.Entry.

Åtgärder

Anropa ChangeTracker.DetectChanges() explicit innan du anropar Entry för att säkerställa beteendet före 3.0.

Sträng- och byte-array-nycklar genereras inte av klienten som standard

spårningsproblem #14617

Gammalt beteende

Före EF Core 3.0 kan string och byte[] nyckelegenskaper användas utan att uttryckligen ange ett värde som inte är null. I sådana fall genereras nyckelvärdet på klienten som en GUID, serialiserat till bytes för byte[].

Nytt beteende

Från och med EF Core 3.0 genereras ett undantag som anger att inget nyckelvärde har angetts.

Varför

Den här ändringen gjordes eftersom klientgenererade string/byte[] värden i allmänhet inte är användbara, och standardbeteendet gjorde det svårt att resonera om genererade nyckelvärden på ett vanligt sätt.

Åtgärder

Beteendet före 3.0 kan hämtas genom att uttryckligen ange att nyckelegenskaperna ska använda genererade värden om inget annat värde som inte är null har angetts. Till exempel med api:et fluent:

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

Eller med dataanteckningar:

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

ILoggerFactory är nu en begränsad tjänst

spårningsproblem #14698

Gammalt beteende

Innan EF Core 3.0 registrerades ILoggerFactory som en singleton-tjänst.

Nytt beteende

Från och med EF Core 3.0 är ILoggerFactory nu registrerad som scope-bunden.

Varför

Den här ändringen gjordes för att tillåta association av en loggare med en DbContext-instans, vilket möjliggör andra funktioner och tar bort vissa fall av patologiskt beteende, till exempel en explosion av interna tjänstleverantörer.

Åtgärder

Den här ändringen bör inte påverka programkoden om den inte registrerar och använder anpassade tjänster på den interna EF Core-tjänstleverantören. Det här är inte vanligt. I dessa fall fungerar det mesta fortfarande, men alla singleton-tjänster som var beroende av ILoggerFactory måste ändras för att få ILoggerFactory på ett annat sätt.

Om du stöter på sådana här situationer kan du skicka in ett problem på EF Core GitHub-utfärdare för att meddela oss hur du använder ILoggerFactory så att vi bättre kan förstå hur vi inte kan bryta detta igen i framtiden.

Proxyservrar med lat inläsning förutsätter inte längre att navigeringsegenskaperna är helt inlästa

spårningsproblem #12780

Gammalt beteende

Innan EF Core 3.0, när en DbContext togs bort, fanns det inget sätt att veta om en viss navigeringsegenskap på en entitet som hämtats från den kontexten var helt inläst eller inte. Proxyservrar förutsätter i stället att en referensnavigering läses in om den har ett värde som inte är null och att en samlingsnavigering läses in om den inte är tom. I dessa fall skulle det vara en no-opatt försöka använda lazy loading.

Nytt beteende

Från och med EF Core 3.0 håller proxyservrar reda på om en navigeringsegenskap läses in eller inte. Det innebär att försök att komma åt en navigeringsegenskap som läses in när kontexten har tagits bort alltid är en no-op, även när den inlästa navigeringen är tom eller null. Om du försöker komma åt en navigeringsegenskap som inte läses in genereras ett undantag om kontexten tas bort även om navigeringsegenskapen är en icke-tom samling. Om den här situationen uppstår innebär det att programkoden försöker använda lazy-loading vid en ogiltig tidpunkt, och programmet bör ändras för att inte göra detta.

Varför

Den här ändringen gjordes för att göra beteendet konsekvent och korrekt vid försök att fördröja inläsningen på en avvecklad DbContext-instans.

Åtgärder

Uppdatera programkoden så att den inte försöker sen inladdning med en frigjord kontext, eller konfigurera detta som en no-op enligt beskrivningen i undantagsmeddelandet.

Överdrivet skapande av interna tjänstleverantörer är nu ett fel som standard

spårningsproblem #10236

Gammalt beteende

Innan EF Core 3.0 loggas en varning för ett program som skapar ett patologiskt antal interna tjänstleverantörer.

Nytt beteende

Från och med EF Core 3.0 behandlas denna varning nu som ett fel och ett undantag kastas.

Varför

Den här ändringen gjordes för att skapa bättre programkod genom att exponera det här patologiska fallet mer explicit.

Åtgärder

Den lämpligaste åtgärden när du stöter på det här felet är att förstå rotorsaken och sluta skapa så många interna tjänstleverantörer. Felet kan dock konverteras tillbaka till en varning (eller ignoreras) via konfigurationen på DbContextOptionsBuilder. Till exempel:

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

Nytt beteende för HasOne/HasMany som anropas med en enda sträng

spårningsproblem #9171

Gammalt beteende

Innan EF Core 3.0 tolkades kodanropet HasOne eller HasMany med en enda sträng på ett förvirrande sätt. Till exempel:

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

Koden ser ut att relatera Samurai till någon annan entitetstyp med hjälp av Entrance navigeringsegenskap, som kan vara privat.

I själva verket försöker den här koden skapa en relation till någon entitetstyp som kallas Entrance utan navigeringsegenskap.

Nytt beteende

Från och med EF Core 3.0 gör koden ovan nu vad den borde ha gjort tidigare.

Varför

Det gamla beteendet var mycket förvirrande, särskilt när du läste konfigurationskoden och letade efter fel.

Åtgärder

Detta bryter bara program som uttryckligen konfigurerar relationer med hjälp av strängar för typnamn och utan att uttryckligen ange navigeringsegenskapen. Det här är inte vanligt. Det tidigare beteendet kan uppnås genom att uttryckligen skicka null för navigeringsegenskapens namn. Till exempel:

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

Returtypen för flera asynkrona metoder har ändrats från Aktivitet till ValueTask

spårningsproblem #15184

Gammalt beteende

Följande asynkrona metoder returnerade tidigare en Task<T>:

  • DbContext.FindAsync()
  • DbSet.FindAsync()
  • DbContext.AddAsync()
  • DbSet.AddAsync()
  • ValueGenerator.NextValueAsync() (och derivatklasser)

Nytt beteende

De ovan nämnda metoderna returnerar nu en ValueTask<T> över samma T som tidigare.

Varför

Den här ändringen minskar antalet heapallokeringar som uppstår när du anropar dessa metoder, vilket förbättrar den allmänna prestandan.

Åtgärder

Program som bara väntar på api:erna ovan behöver bara kompileras om – inga källändringar krävs. En mer komplex användning (t.ex. att skicka den returnerade Task till Task.WhenAny()) kräver vanligtvis att den returnerade ValueTask<T> konverteras till en Task<T> genom att anropa AsTask() på den. Observera att detta negerar allokeringsminskningen som den här ändringen medför.

Anmärkningen Relational:TypeMapping är nu endast TypeMapping

spårningsproblem #9913

Gammalt beteende

Anteckningsnamnet för typmappningsanteckningar var "Relational:TypeMapping".

Nytt beteende

Anteckningsnamnet för typmappningsanteckningar är nu "TypeMapping".

Varför

Typmappningar används nu för mer än bara relationsdatabasprovidrar.

Åtgärder

Detta kommer endast att bryta program som direkt använder typmappningen som en annotering, vilket inte är vanligt. Den lämpligaste åtgärden att åtgärda är att använda API-ytan för att komma åt typmappningar i stället för att använda kommentaren direkt.

ToTable på en härledd typ genererar ett undantag

spårningsproblem #11811

Gammalt beteende

Innan EF Core 3.0 skulle ToTable(), som anropades på en härledd typ, ignoreras eftersom arvsmappningsstrategin var begränsad till TPH, vilket inte är tillämpligt här.

Nytt beteende

Från och med EF Core 3.0 och som förberedelse för att lägga till TPT- och TPC-stöd i en senare version, utlöser ToTable() som anropas för en härledd typ nu ett undantag för att undvika en oväntad mappningsändring i framtiden.

Varför

För närvarande är det inte giltigt att mappa en härledd typ till en annan tabell. Den här ändringen undviker att gå sönder i framtiden när det blir en accepterad sak att göra.

Åtgärder

Ta bort alla försök att mappa härledda typer till andra tabeller.

ForSqlServerHasIndex ersatt med HasIndex

spårningsproblem #12366

Gammalt beteende

Före EF Core 3.0 gav ForSqlServerHasIndex().ForSqlServerInclude() ett sätt att konfigurera kolumner som används med INCLUDE.

Nytt beteende

Från och med EF Core 3.0 stöds nu användning av Include på ett index på relationsnivå. Använd HasIndex().ForSqlServerInclude().

Varför

Den här ändringen gjordes för att konsolidera API:et för index med Include till en plats för alla databasprovidrar.

Åtgärder

Använd det nya API:et, som du ser ovan.

Metadata-API-ändringar

spårningsproblem #214

Nytt beteende

Följande egenskaper konverterades till tilläggsmetoder:

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

Varför

Den här ändringen förenklar implementeringen av ovan nämnda gränssnitt.

Åtgärder

Använd de nya tilläggsmetoderna.

Ändringar i providerspecifikt metadata-API

spårningsproblem #214

Nytt beteende

De providerspecifika tilläggsmetoderna plattas ut:

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

Varför

Den här ändringen förenklar genomförandet av de ovannämnda tilläggsmetoderna.

Åtgärder

Använd de nya tilläggsmetoderna.

EF Core skickar inte längre pragma för SQLite FK-tillämpning

spårningsproblem #12151

Gammalt beteende

Innan EF Core 3.0 skickar EF Core PRAGMA foreign_keys = 1 när en anslutning till SQLite öppnas.

Nytt beteende

Från och med EF Core 3.0 skickar EF Core inte längre PRAGMA foreign_keys = 1 när en anslutning till SQLite öppnas.

Varför

Den här ändringen gjordes eftersom EF Core använder SQLitePCLRaw.bundle_e_sqlite3 som standard, vilket i sin tur innebär att FK-tillämpningen är aktiverad som standard och inte behöver aktiveras uttryckligen varje gång en anslutning öppnas.

Åtgärder

Främmande nycklar är aktiverade som standard i SQLitePCLRaw.bundle_e_sqlite3, vilket används för EF Core. I andra fall kan främmande nycklar aktiveras genom att ange Foreign Keys=True i anslutningssträngen.

Microsoft.EntityFrameworkCore.Sqlite är nu beroende av SQLitePCLRaw.bundle_e_sqlite3

Gammalt beteende

Före EF Core 3.0 använde EF Core SQLitePCLRaw.bundle_green.

Nytt beteende

Från och med EF Core 3.0 använder EF Core SQLitePCLRaw.bundle_e_sqlite3.

Varför

Den här ändringen gjordes så att den version av SQLite som används på iOS överensstämmer med andra plattformar.

Åtgärder

Om du vill använda den interna SQLite-versionen på iOS konfigurerar du Microsoft.Data.Sqlite att använda ett annat SQLitePCLRaw paket.

Guid-värden lagras nu som TEXT på SQLite

spårningsproblem #15078

Gammalt beteende

Guid-värden lagrades tidigare som BLOB-värden på SQLite.

Nytt beteende

Guid-värden lagras nu som TEXT.

Varför

Det binära formatet för Guids är inte standardiserat. Om du lagrar värdena som TEXT blir databasen mer kompatibel med andra tekniker.

Åtgärder

Du kan migrera befintliga databaser till det nya formatet genom att köra SQL på följande sätt.

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

I EF Core kan du också fortsätta att använda det tidigare beteendet genom att konfigurera en värdekonverterare för dessa egenskaper.

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

Microsoft.Data.Sqlite kan fortfarande läsa Guid-värden från både BLOB- och TEXT-kolumner. Men eftersom standardformatet för parametrar och konstanter har ändrats måste du förmodligen vidta åtgärder för de flesta scenarier som involverar Guids.

Teckenvärden lagras nu som TEXT på SQLite

spårningsproblem #15020

Gammalt beteende

Teckenvärden lagrades tidigare som INTEGER-värden på SQLite. Till exempel lagrades ett teckenvärde för A som heltalsvärdet 65.

Nytt beteende

Teckenvärden lagras nu som TEXT.

Varför

Att lagra värdena som TEXT är mer naturligt och gör databasen mer kompatibel med andra tekniker.

Åtgärder

Du kan migrera befintliga databaser till det nya formatet genom att köra SQL på följande sätt.

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

I EF Core kan du också fortsätta att använda det tidigare beteendet genom att konfigurera en värdekonverterare för dessa egenskaper.

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

Microsoft.Data.Sqlite kan också läsa teckenvärden från både INTEGER- och TEXT-kolumner, så vissa scenarier kanske inte kräver någon åtgärd.

Migrerings-ID:t genereras nu med hjälp av den invarianta kulturens kalender

spårningsproblem #12978

Gammalt beteende

Migrerings-ID:t genererades oavsiktligt med hjälp av den aktuella kulturens kalender.

Nytt beteende

Migrerings-ID:t genereras nu alltid med hjälp av den invarianta kulturens kalender (gregoriansk).

Varför

Migreringsordningen är viktig när du uppdaterar databasen eller löser sammanslagningskonflikter. Med hjälp av den invarianta kalendern undviker du ordningsproblem som kan uppstå när gruppmedlemmar har olika systemkalendrar.

Åtgärder

Den här ändringen påverkar alla som använder en icke-gregoriansk kalender där året är större än den gregorianska kalendern (som den thailändska buddistiska kalendern). Befintliga migrerings-ID:n måste uppdateras så att nya migreringar ordnas efter befintliga migreringar.

Migrerings-ID:t finns i migreringsattributet i migreringsdesignerfilerna.

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

Tabellen Migreringshistorik måste också uppdateras.

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

UseRowNumberForPaging har tagits bort

spårningsproblem #16400

Gammalt beteende

Innan EF Core 3.0 kunde UseRowNumberForPaging användas för att generera SQL för sidindelning som är kompatibel med SQL Server 2008.

Nytt beteende

Från och med EF Core 3.0 genererar EF endast SQL för paginering som endast är kompatibelt med nyare versioner av SQL Server.

Varför

Vi gör den här ändringen eftersom SQL Server 2008 inte längre är en produkt som stöds och det är ett betydande arbete att uppdatera den här funktionen för att arbeta med frågeändringarna som gjorts i EF Core 3.0.

Åtgärder

Vi rekommenderar att du uppdaterar till en nyare version av SQL Server eller använder en högre kompatibilitetsnivå, så att den genererade SQL stöds. Med detta sagt, om du inte kan göra detta kan du kommentera spårningsproblemet med information. Vi kan komma att återkomma till det här beslutet baserat på feedback.

Tilläggsinformation/metadata har tagits bort från IDbContextOptionsExtension

spårningsproblem #16119

Gammalt beteende

IDbContextOptionsExtension innehåller metoder för att tillhandahålla metadata om tillägget.

Nytt beteende

Dessa metoder har flyttats till en ny DbContextOptionsExtensionInfo abstrakt basklass, som returneras från en ny IDbContextOptionsExtension.Info egenskap.

Varför

I versionerna från 2.0 till 3.0 behövde vi lägga till eller ändra dessa metoder flera gånger. Om du delar upp dem i en ny abstrakt basklass blir det enklare att göra den här typen av ändringar utan att bryta befintliga tillägg.

Åtgärder

Uppdatera tillägg för att följa det nya mönstret. Exempel finns i många implementeringar av IDbContextOptionsExtension för olika typer av tillägg i EF Core-källkoden.

LogQueryPossibleExceptionWithAggregateOperator har bytt namn

spårningsproblem #10985

Förändring

RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator har bytt namn till RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning.

Varför

Justerar namngivningen av den här varningshändelsen med alla andra varningshändelser.

Åtgärder

Använd det nya namnet. (Observera att händelse-ID-numret inte har ändrats.)

Förtydliga API:et för namn på främmande nyckelbegränsningar

spårningsproblem #10730

Gammalt beteende

Före EF Core 3.0 kallades främmande nyckelns begränsningsnamn helt enkelt för "namn". Till exempel:

var constraintName = myForeignKey.Name;

Nytt beteende

Från och med EF Core 3.0 kallas namn på främmande nyckelvillkor nu för "villkorsnamn". Till exempel:

var constraintName = myForeignKey.ConstraintName;

Varför

Den här ändringen ger konsekvens i namngivning i det här området och klargör även att det här är namnet på villkoret för sekundärnyckeln, och inte kolumnen eller egenskapsnamnet som sekundärnyckeln definieras på.

Åtgärder

Använd det nya namnet.

IRelationalDatabaseCreator.HasTables/HasTablesAsync har blivit offentliga

spårningsproblem #15997

Gammalt beteende

Före EF Core 3.0 skyddades dessa metoder.

Nytt beteende

Från och med EF Core 3.0 är dessa metoder offentliga.

Varför

Dessa metoder används av EF för att avgöra om en databas skapas men är tom. Detta kan också vara användbart utanför EF när du avgör om migreringar ska tillämpas eller inte.

Minskningar

Ändra tillgängligheten för alla överstyrningar.

Microsoft.EntityFrameworkCore.Design är nu ett DevelopmentDependency-paket

spårningsproblem #11506

Gammalt beteende

Före EF Core 3.0 var Microsoft.EntityFrameworkCore.Design ett vanligt NuGet-paket vars sammansättning kunde refereras till av projekt som var beroende av det.

Nytt beteende

Från och med EF Core 3.0 är det ett DevelopmentDependency-paket. Det innebär att beroendet inte flödar transitivt till andra projekt och att du inte längre som standard kan referera till dess sammansättning.

Varför

Det här paketet är endast avsett att användas vid designtillfället. Distribuerade program bör inte referera till det. Att göra paketet till ett DevelopmentDependency förstärker den här rekommendationen.

Åtgärder

Om du behöver referera till det här paketet för att åsidosätta EF Cores designtidsbeteende kan du uppdatera PackageReference-objektmetadata i projektet.

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

Om paketet refereras transitivt via Microsoft.EntityFrameworkCore.Tools måste du lägga till en explicit PackageReference i paketet för att ändra dess metadata. En sådan explicit referens måste läggas till i alla projekt där typerna från paketet behövs.

SQLitePCL.raw uppdaterad till version 2.0.0

spårningsproblem #14824

Gammalt beteende

Microsoft.EntityFrameworkCore.Sqlite var tidigare beroende av version 1.1.12 av SQLitePCL.raw.

Nytt beteende

Vi har uppdaterat vårt paket så att det beror på version 2.0.0.

Varför

Version 2.0.0 av SQLitePCL.raw riktar sig mot .NET Standard 2.0. Den var tidigare riktad mot .NET Standard 1.1 som krävde en stor stängning av transitiva paket för att fungera.

Åtgärder

SQLitePCL.raw version 2.0.0 innehåller några icke-bakåtkompatibla ändringar. Mer information finns i utgivningsanteckningar.

NetTopologySuite har uppdaterats till version 2.0.0

spårningsproblem #14825

Gammalt beteende

De rumsliga paket som tidigare var beroende av version 1.15.1 av NetTopologySuite.

Nytt beteende

Vi har uppdaterat vårt paket så att det är beroende av version 2.0.0.

Varför

Version 2.0.0 av NetTopologySuite syftar till att åtgärda flera användbarhetsproblem som EF Core-användare stöter på.

Åtgärder

NetTopologySuite version 2.0.0 innehåller vissa icke-bakåtkompatibla ändringar. För mer information, se versionsinformation.

Microsoft.Data.SqlClient används i stället för System.Data.SqlClient

spårningsproblem #15636

Gammalt beteende

Microsoft.EntityFrameworkCore.SqlServer var tidigare beroende av System.Data.SqlClient.

Nytt beteende

Vi har uppdaterat vårt paket så att det är beroende av Microsoft.Data.SqlClient.

Varför

Microsoft.Data.SqlClient är huvuddrivrutinen för dataåtkomst för SQL Server framöver och System.Data.SqlClient är inte längre i fokus för utveckling. Vissa viktiga funktioner, till exempel Always Encrypted, är endast tillgängliga på Microsoft.Data.SqlClient.

Åtgärder

Om koden är direkt beroende av System.Data.SqlClient måste du ändra den så att den refererar till Microsoft.Data.SqlClient i stället. eftersom de två paketen har en mycket hög grad av API-kompatibilitet bör detta bara vara ett enkelt paket och namnområdesändring.

Flera tvetydiga självrefererande relationer måste konfigureras

spårningsproblem #13573

Gammalt beteende

En entitetstyp med flera självrefererande uni-directional navigeringsegenskaper och matchande FK:er har felaktigt konfigurerats som en enda relation. Till exempel:

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

Nytt beteende

Det här scenariot identifieras nu i modellbygget och ett undantag genereras som indikerar att modellen är tvetydig.

Varför

Den resulterande modellen var tvetydig och kommer sannolikt vanligtvis att vara fel för det här fallet.

Åtgärder

Använd fullständig konfiguration av relationen. Till exempel:

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

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

DbFunction.Schema som är null eller tom sträng konfigurerar att det finns i modellens standardschema

spårningsproblem #12757

Gammalt beteende

En DbFunction som konfigurerats med schemat som en tom sträng behandlades som en inbyggd funktion utan schema. Följande kod mappar till exempel DatePart CLR-funktion till DATEPART inbyggd funktion i SqlServer.

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

Nytt beteende

Alla DbFunction-mappningar anses vara mappade till användardefinierade funktioner. Därför skulle ett tomt strängvärde placera funktionen i standardschemat för modellen. Vilket kan vara schemat som är konfigurerat explicit via fluent API modelBuilder.HasDefaultSchema(), eller dbo annars.

Varför

Tidigare var schemat tomt på ett sätt att behandla att funktionen är inbyggd, men den logiken gäller endast för SqlServer där inbyggda funktioner inte tillhör något schema.

Åtgärder

Konfigurera DbFunctions översättning manuellt för att mappa den till en inbyggd funktion.

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

EF Core 3.0 riktar sig mot .NET Standard 2.1 i stället för .NET Standard 2.0 återställd

spårningsproblem #15498

EF Core 3.0 riktar sig mot .NET Standard 2.1, vilket är en brytförändring som exkluderar .NET Framework-program. EF Core 3.1 återställde detta och riktar in sig på .NET Standard 2.0 igen.

Frågekörning loggas på felsökningsnivå återställd

spårningsproblem #14523

Vi har återställt den här ändringen eftersom den nya konfigurationen i EF Core 3.0 tillåter att loggnivån för alla händelser anges av programmet. Om du till exempel vill växla loggning av SQL till Debugkonfigurerar du explicit nivån i OnConfiguring eller AddDbContext:

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