Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Waarschuwing
NativeAOT en queryvoorcompilatie zijn zeer experimentele functies en zijn nog niet geschikt voor productiegebruik. De hieronder beschreven ondersteuning moet worden bekeken als infrastructuur voor de uiteindelijke functie, die in een toekomstige versie wordt uitgebracht. We moedigen u aan te experimenteren met de huidige ondersteuning en over uw ervaringen te rapporteren, maar raden af om EF NativeAOT-toepassingen in productie te implementeren. Zie hieronder voor specifieke bekende beperkingen.
.NET NativeAOT staat het publiceren van zelfstandige .NET-toepassingen toe die vooraf zijn gecompileerd (AOT). Dit biedt de volgende voordelen:
- Aanzienlijk snellere opstarttijd van toepassingen
- Kleine, zelfstandige binaire bestanden met kleinere geheugenvoetafdrukken en eenvoudiger te implementeren
- Toepassingen uitvoeren in omgevingen waarbij Just-In-Time-compilatie niet wordt ondersteund
EF-toepassingen die zijn gepubliceerd met NativeAOT, starten veel sneller dan dezelfde toepassingen zonder deze. Naast de algemene .NET-opstartverbeteringen die NativeAOT biedt (dus geen JIT-compilatie vereist telkens), worden LINQ-query's vooraf gecompileert bij het publiceren van uw toepassing, zodat er geen verwerking nodig is bij het opstarten en de SQL al beschikbaar is voor onmiddellijke uitvoering. Hoe meer EF LINQ-query's een toepassing in de code heeft, hoe sneller de opstartwinst wordt verwacht.
Een EF NativeAOT-toepassing publiceren
Schakel eerst NativeAOT-publicatie in voor uw project als volgt:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
De ondersteuning van EF voor het uitvoeren van LINQ-query's onder NativeAOT is afhankelijk van precompilatie van query's: dit mechanisme identificeert EF LINQ-query's statisch en genereert C#- interceptors, die code bevatten om elke specifieke query uit te voeren. Dit kan de opstarttijd van uw toepassing aanzienlijk verminderen, omdat het zware werk van de verwerking en het compileren van uw LINQ-query's in SQL niet meer gebeurt wanneer uw toepassing wordt gestart. In plaats daarvan bevat de interceptor van elke query de voltooide SQL voor die query, evenals geoptimaliseerde code voor het materialiseren van databaseresultaten als .NET-objecten.
C#-interceptors zijn momenteel een experimentele functie en vereisen een speciale aanmelding in uw projectbestand:
<PropertyGroup>
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.EntityFrameworkCore.GeneratedInterceptors</InterceptorsNamespaces>
</PropertyGroup>
Ten slotte bevat het Microsoft.EntityFrameworkCore.Tasks pakket MSBuild-integratie waarmee de queryvoorcompilatie wordt uitgevoerd (en het vereiste gecompileerde model wordt gegenereerd) wanneer u uw toepassing publiceert:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tasks" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
U bent nu klaar om uw EF NativeAOT-toepassing te publiceren:
dotnet publish -r linux-arm64 -c Release
Opmerking
De publicatieopdracht kan mislukken met een fout CS9137. De oorzaak van deze fout zijn verouderde transitieve pakketverwijzingen Microsoft.CodeAnalysis.CSharp.Workspaces en Microsoft.CodeAnalysis.Workspaces.MSBuild. Als tijdelijke oplossing voegt u deze pakketten expliciet toe aan uw .csproj-bestand:
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.13.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.13.0" />
Zie dit onderwerp voor meer informatie.
Dit toont het publiceren van een NativeAOT-publicatie voor Linux die wordt uitgevoerd op ARM64; raadpleeg deze catalogus om uw runtime-id te vinden. Als u de interceptors wilt genereren zonder te publiceren, bijvoorbeeld om de gegenereerde bronnen te onderzoeken, kunt u dit doen via de dotnet ef dbcontext optimize --precompile-queries --nativeaot opdracht.
Vanwege de manier waarop C#-interceptors werken, worden deze ongeldig gemaakt door elke wijziging in de toepassingsbron en moet het bovenstaande proces worden herhaald. Als gevolg hiervan wordt verwacht dat de generatie van onderscheppers en het daadwerkelijke publiceren niet zal plaatsvinden in de binnenste lus, omdat de ontwikkelaar aan code werkt. In plaats daarvan kunnen zowel dotnet ef dbcontext optimize als dotnet publish worden uitgevoerd in een werkstroom voor publiceren/implementeren, in een CI/CD-systeem.
Opmerking
Het publiceren meldt momenteel een aantal trim- en NativeAOT-waarschuwingen, wat betekent dat uw toepassing niet volledig gegarandeerd goed zal werken. Dit wordt verwacht op basis van de huidige experimentele status van NativeAOT-ondersteuning; de laatste, niet-experimentele functie rapporteert geen waarschuwingen.
Beperkingen
Dynamische query's worden niet ondersteund
Queryvoorcompilatie voert een statische analyse uit van uw broncode, waarbij EF LINQ-query's worden geïdentificeerd en C#-snijpunten voor deze query's worden gegenereerd. LINQ maakt het mogelijk om zeer dynamische query's uit te drukken, waarbij LINQ-operators zijn samengesteld op basis van willekeurige voorwaarden; dergelijke query's kunnen helaas niet statisch worden geanalyseerd en worden momenteel niet ondersteund. Bekijk het volgende voorbeeld:
IAsyncEnumerable<Blog> GetBlogs(BlogContext context, bool applyFilter)
{
IQueryable<Blog> query = context.Blogs.OrderBy(b => b.Id);
if (applyFilter)
{
query = query.Where(b => b.Name != "foo");
}
return query.AsAsyncEnumerable();
}
De bovenstaande query wordt verdeeld over verschillende instructies en stelt de Where operator dynamisch samen op basis van een externe parameter. Dergelijke query's kunnen niet vooraf worden gecompileerd. Het is echter soms mogelijk om dergelijke dynamische query's te herschrijven als meerdere niet-dynamische query's:
IAsyncEnumerable<Blog> GetBlogs(BlogContext context, bool applyFilter)
=> applyFilter
? context.Blogs.OrderBy(b => b.Id).Where(b => b.Name != "foo").AsAsyncEnumerable()
: context.Blogs.OrderBy(b => b.Id).AsAsyncEnumerable();
Omdat de twee query's statisch kunnen worden geanalyseerd van begin tot eind, kan precompilatie deze afhandelen.
Houd er rekening mee dat dynamische query's in de toekomst waarschijnlijk worden ondersteund bij het gebruik van NativeAOT; omdat ze echter niet vooraf kunnen worden gecompileerd, blijven ze het opstarten van uw toepassing vertragen en zullen ze doorgaans ook minder efficiënt presteren in vergelijking met niet-NativeAOT-uitvoering; dit komt doordat EF intern afhankelijk is van het genereren van code om databaseresultaten te materialiseren, maar het genereren van code wordt niet ondersteund bij het gebruik van NativeAOT.
Andere beperkingen
- Syntaxis van LINQ-queryexpressie (soms aangeduid als 'begripssyntaxis') wordt niet ondersteund.
- De gegenereerde gecompileerde model- en query-interceptors kunnen momenteel behoorlijk groot zijn qua codegrootte en kunnen een lange tijd duren om te genereren. We zijn van plan dit te verbeteren.
- EF-providers moeten mogelijk ondersteuning bouwen voor vooraf gecompileerde query's; raadpleeg de documentatie van uw provider om te weten of deze compatibel is met de nativeAOT-ondersteuning van EF.
- Waardeconversieprogramma's die gebruikmaken van vastgelegde status worden niet ondersteund.
Vooraf gecompileerde query's zonder NativeAOT
Vanwege de huidige beperkingen van de nativeAOT-ondersteuning van EF is het mogelijk niet bruikbaar voor sommige toepassingen. U kunt echter mogelijk profiteren van vooraf gecompileerde query's tijdens het publiceren van reguliere, niet-NativeAOT-toepassingen; Hierdoor kunt u ten minste profiteren van de opstarttijdvermindering die vooraf gecompileerde query's bieden, terwijl u dynamische query's en andere functies kunt gebruiken die momenteel niet worden ondersteund met NativeAOT.
Het gebruik van vooraf gecompileerde query's zonder NativeAOT is gewoon een kwestie van het uitvoeren van het volgende:
dotnet ef dbcontext optimize --precompile-queries
Zoals hierboven wordt weergegeven, genereert dit een gecompileerd model en interceptors voor query's die vooraf kunnen worden gecompileerd, waardoor de overhead van de opstarttijd van uw toepassing wordt verwijderd.