Als je hebt geprobeerd om te verzenden .NET toepassingen als single, native executables met behulp van Native AOT, je hebt waarschijnlijk lopen face-first in de SQLite muur. U krijgt alles geconfigureerd, de bouw voltooid met succes, en dan [...] boom runtime crashes met cryptische DllNotFoundException fouten over e_sqlite3. Laat me je de uren van frustratie die ik heb meegemaakt besparen en je precies laten zien hoe je SQLite kunt laten werken met Native AOT in Windows, Linux (inclusief ARM64 Raspberry Pi), en macOS.
Laten we beginnen met de absolute basics. Als je ooit een .NET applicatie hebt gebouwd en je afvraagt waarom je de ".NET Runtime" op servers moet installeren of waarom je console app een seconde nodig heeft om de eerste keer dat je het uitvoert te starten, is AOT het antwoord op deze problemen.
Wanneer je C# code schrijft en je applicatie bouwt, produceert de compiler geen machinecode die je CPU direct kan uitvoeren. In plaats daarvan produceert het iets genaamd **Tussentaal (IL)**Denk erover na als halverwege tussen uw C# code en de werkelijke machine instructies.
Als je je .NET app draait, gebeurt dit:
Dit is als het hebben van een vertaler die uw recept (IL) leest en het verbaal vertaalt naar een chef (CPU) regel voor regel tijdens het koken. Het werkt, maar er is overhead:
Native AOT draait dit model op zijn kop. In plaats van het vertalen van uw code op runtime, het vertaalt alles bij bouwtijd. Je eindigt met een enkel uitvoerbaar bestand dat de werkelijke machinecode bevat die je CPU direct kan draaien geen runtime, geen vertaler, geen wachten.
Denk aan het als het krijgen van een professioneel vertaald recept boek in plaats van het huren van een live vertaler. Het werk is gedaan een keer, vooraf, en het resultaat is klaar om onmiddellijk te gebruiken.
Dit is wat Native AOT je geeft:
1. Kleine uitvoerbare bestanden: 10-30MB in plaats van 150MB+
Uw app en alles wat het nodig heeft wordt gecompileerd in een kleine binaire. Geen aparte runtime bestanden.
2. Instant opstarten: 80% snellere koude start
Mijn tests: normaal .NET nam ~800ms om te beginnen, AOT nam ~150ms. Er is geen JIT warm-up tijd de machine code is klaar om onmiddellijk uit te voeren.
3. Nul afhankelijkheden: Geen .NET runtime vereist
U kunt uw uitvoerbaar bestand kopiëren naar elke machine met de juiste OS (Windows/Linux/Mac) en het draait gewoon. Geen "install .NET 9 Runtime" voorwaarde.
4. Lager geheugengebruik: Ongeveer 50% minder geheugen
Geen JIT compiler zitten in het geheugen. In mijn gateway applicatie, normaal .NET gebruikt 85MB inactief, AOT gebruikt 42MB.
5. Beter voor beperkte omgevingen: Works where JIT can't
Sommige omgevingen (bepaalde Docker containers, iOS, embedded systemen) staan geen runtime code generatie toe. AOT werkt overal.
AOT is geen magie.
1. Geen dynamische codegeneratie
Alles wat code genereert op runtime zal niet werken:
System.Reflection.Emit (dynamisch creëren van typen)De meeste normale .NET code is prima, maar sommige kaders die sterk afhankelijk zijn van reflectie hebben speciale configuratie nodig.
2. Platform-specifieke builds
JIT compilatie produceert IL die draait op elk platform. AOT produceert native machine code voor één specifiek platform. U dient apart te bouwen voor:
We zullen deze automatiseren met GitHub Acties later.
3. Langere bouwtijden
In plaats van te compileren naar IL in seconden, compileert AOT helemaal naar machinecode. Verwacht 2-5 minuten in plaats van 10 seconden. Het is een eenmalige kosten voor permanente voordelen.
4. Sommige functies hebben extra configuratie nodig
JSON serialisatie, Entity Framework, en alles wat gebruik maakt van zware reflectie kan nodig hebben om de compiler expliciet te vertellen welke types te houden. We zullen dit behandelen.
Native AOT is perfect voor:
Skip AOT for:
Voor CLI-tools, microservices, containers en randapparatuur zijn de verbeteringen game-changing. Maar er is een vangst wanneer u databases toevoegen specifiek SQLite.
Nu je begrijpt wat AOT is, laten we het hebben over het enige grootste pijnpunt: SQLite. Dit is de muur die de meeste mensen raken bij het proberen om AOT te gebruiken met database-backed applicaties.
Hier is de typische reis:
Microsoft.Data.Sqlite naar uw projectPublishAot=true in uw .csprojDllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies
Je app crasht voordat het iets kan doen.
Om het probleem te begrijpen, moet je weten over native libraries.
SQLite is niet geschreven in .NET. Het is geschreven in C. Het is gecompileerd naar platform-specifieke native code:
e_sqlite3.dll op Windowslibe_sqlite3.so op Linuxlibe_sqlite3.dylib op macOSWanneer u dit middel gebruikt Microsoft.Data.Sqlite in normale .NET, het is gewoon een wrapper rond deze native SQLite bibliotheek. Op runtime, het probeert dynamisch laden het juiste native bestand voor uw platform.
Dit werkt prima bij normaal .NET omdat:
Inheemse AOT heeft twee kenmerken die botsen met de aanpak van SQLite:
1. Agressief trimmen: AOT verwijdert elke code die het denkt dat u niet gebruikt. Als het niet statisch kan bewijzen dat u iets nodig hebt, wordt het verwijderd. Dynamische bibliotheek laden verward de trimmer het kan de verbinding tussen uw code en de native SQLite DLL niet zien.
2. Geen dynamische laadondersteuning: AOT produceert een op zichzelf staand binair. Het verwacht dat alle native afhankelijkheden expliciet gekoppeld worden op compilatietijd, niet dynamisch geladen op runtime.
Het resultaat: Microsoft.Data.Sqlite verwacht een native SQLite-bibliotheek te vinden op runtime, maar AOT heeft het ofwel weggeknipt of weet niet hoe het goed te bundelen.
Nog erger, als je andere NuGet pakketten die gebruik maken van SQLite (zoals sommige ORM bibliotheken of mijn mostlylucid.ephemeral.complete pakket), kunt u eindigen met meerdere incompatibele SQLite providers in je afhankelijkheidsboom.
Elke provider probeert anders te werken:
De AOT compiler raakt in de war over welke te gebruiken, en vaak het resultaat is dat het geen van hen of erger omvat, bevat conflicterende bestanden die niet samen kunnen werken.
Na uren van frustratie, vond ik de oplossing: SQLitePCLRaw.bundle_e_sqlite3. Dit is een speciaal NuGet pakket speciaal ontworpen om te werken met AOT.
Voeg deze twee pakketten toe aan uw project:
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
</ItemGroup>
De bundle_e_sqlite3 pakket is anders dan normale SQLite providers:
1. Het omvat voorgecompileerde native SQLite bibliotheken voor elk groot platform:
2. Deze native bibliotheken zijn verpakt op een manier die de AOT compiler begrijpt
De bundel markeert de oorspronkelijke afhankelijkheden expliciet zodat de AOT compiler weet om ze in de uiteindelijke binaire op te nemen. Geen dynamisch laden, geen runtime zoeken naar bestanden.
3. Het is ontworpen voor cross-platform builds
Een pakket werkt voor alle platforms. Je hebt geen platformspecifieke pakketten of voorwaardelijke referenties nodig.
Herinner je je de twee problemen die we ontdekten?
Probleem 1: AOT's trimmen verwijdert bibliotheken die het niet kan zien worden gebruikt
Probleem 2: AOT ondersteunt dynamisch laden niet
Het resultaat: wanneer u voor Windows x64 bouwt, bevat de bundel e_sqlite3.dll. Wanneer je bouwt voor Linux ARM64, bevat het de ARM64 libe_sqlite3.soAlles werkt gewoon.
Hier is het deel dat 90% van de mensen die proberen om SQLite te gebruiken met AOT struikelt, inclusief mij bij mijn eerste poging.
Met normaal .NET, de SQLite bundel initialiseert zichzelf automatisch de eerste keer dat u SQLite gebruikt. Magie gebeurt achter de schermen te doen je hoeft niets te doen.
Met inheemse AOT, deze automatische initialisatie werkt niet. De AOT compiler kan de automatische opstartcode niet zien (het ziet eruit als ongebruikte code en wordt getrimd), zodat u moet handmatig initialiseren de bundel bij het begin van uw toepassing.
Hier is de magische lijn die je nodig hebt:
using SQLitePCL;
public class Program
{
public static void Main(string[] args)
{
// THIS IS CRITICAL: Initialize SQLite FIRST, before ANYTHING else
SQLitePCL.Batteries.Init();
// Now you can do normal application setup
var builder = WebApplication.CreateBuilder(args);
// This is now safe - SQLite is initialized
builder.Services.AddDbContext<MyDbContext>(options =>
options.UseSqlite("Data Source=app.db"));
var app = builder.Build();
app.Run();
}
}
Batteries.Init() Doen?Deze methode vertelt de SQLite bundel om:
Microsoft.Data.Sqlite en de moedertaalbibliotheekHet heet "Batteries" omdat het de "Batteries Included" bundel is alles wat je nodig hebt is verpakt samen.
Zet Batteries.Init() als de eerste regel in uw Main methode, vóór:
Denk aan het als het aansluiten van een apparaat voordat u probeert om het aan te zetten. Als u probeert om SQLite te gebruiken voordat u belt Init(), je krijgt nog steeds de DllNotFoundException ook al is de DLL correct gebundeld in uw toepassing.
Bent u vergeten te bellen? Batteries.Init(), uw app zal:
DllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies
Dit is verwarrend omdat de DLL is gebundeld in uw toepassing het is gewoon niet geïnitialiseerd. Ik verloor twee uur aan deze fout. Wees niet zoals ik.
Hier is een volle .csproj geconfigureerd voor multi-platform Native AOT met SQLite:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Native AOT -->
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<InvariantGlobalization>true</InvariantGlobalization>
<!-- Single File -->
<PublishSingleFile>true</PublishSingleFile>
<StripSymbols>true</StripSymbols>
<!-- Optimization -->
<OptimizationPreference>Speed</OptimizationPreference>
<!-- Multi-platform targets -->
<RuntimeIdentifiers>
win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64
</RuntimeIdentifiers>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
</ItemGroup>
</Project>
Laat me opsplitsen wat elk van deze instellingen doet:
PublishAot=true
Dit is de master switch die Native AOT compilatie mogelijk maakt. Zonder dit, krijg je normaal .NET gedrag (JIT compilatie). Hiermee krijg je vooraf gecompileerde native code.
PublishTrimmed=true en TrimMode=full
Deze vertellen de compiler om elke code die u niet gebruikt te verwijderen. Denk aan het als het schoonmaken van uw garage voor het verplaatsen waarom pak je dingen die je niet nodig hebt?
PublishTrimmed=true maakt het afknippen mogelijkTrimMode=full "Wees agressief, verwijder alles wat je kunt"Waarschuwing: Dit kan code breken die gebruik maakt van zware reflectie (zoals sommige JSON serializers of ORMs) omdat de trimmer niet altijd kan zien wat je gebruikt via reflectie.
InvariantGlobalization=true
Dit verwijdert alle cultuur-specifieke gegevens van uw app formaten, valuta symbolen, tekst sorteren regels voor verschillende talen. Bespaart 5-10MB.
Stel dit alleen in op true als uw app:
Als je een CLI-tool of API-gateway bouwt die niets om lokalisatie geeft, is dit gratis besparingen. Als je iets bouwt dat data moet formatteren voor Franse gebruikers of Turkse tekst correct sorteren, sla deze instelling dan over.
PublishSingleFile=true
Bundelt alles in één uitvoerbaar bestand.
myapp.exe
myapp.dll
System.Text.Json.dll
... 50 more files
Je krijgt gewoon:
myapp.exe
Veel makkelijker in te zetten.
StripSymbols=true
Debug symbolen helpen debuggers tonen u variabele namen en regelnummers bij het debuggen. Ze zijn nuttig tijdens de ontwikkeling, maar voeg meerdere megabytes aan uw uiteindelijke binaire.
Deze instelling verwijdert ze. Uw app draait precies hetzelfde, gewoon kleiner.
OptimizationPreference=Speed
Dit vertelt de compiler wat te prioriteren bij het nemen van beslissingen:
Speed: Maak het snel (iets grotere binaire bestanden, maar betere prestaties)Size: Maak het klein (iets langzamer, maar minimaal binair formaat)Voor de meeste toepassingen, Speed is de juiste keuze. Het grootteverschil is meestal slechts 2-3MB, maar het prestatieverschil kan worden opgemerkt.
RuntimeIdentifiers
Dit verklaart welke platforms u wilt ondersteunen. Het bouwt ze niet allemaal. Het vertelt alleen tooling "dit zijn geldige doelen."
Beschikbare identificatienummers:
win-x64: Windows 64-bit (Intel/AMD)win-arm64: Windows ARM64 (Surface Pro X, enz.)linux-x64: Linux 64-bit (Ubuntu, Debian, RHEL, enz.)linux-arm64: Linux ARM64 (Raspberry Pi 4/5, AWS Graviton)osx-x64: MacOS Intel (oudere Macs)osx-arm64: macOS Apple Silicium (M1/M2/M3 Macs)Je bouwt één platform tegelijk met dotnet publish -r linux-x64, bijvoorbeeld.
Weet je nog hoe ik zei dat AOT platformspecifieke builds vereist? Je moet apart compileren voor Windows, Linux x64, Linux ARM64, macOS Intel en macOS Apple Silicon. Dit handmatig doen zou vervelend zijn, maar we kunnen het automatiseren.
Als je niet bekend bent, GitHub Acties is een gratis CI/CD (Continuous Integration/Continuous Deployment) service ingebouwd in GitHub. Hiermee kun je geautomatiseerde taken uitvoeren wanneer je code pusht of een release-tag aanmaakt.
Beschouw het als het hebben van een build server die:
v1.0.0Dit alles draait op de servers van GitHub. U hoeft geen infrastructuur te onderhouden. Voor open-source projecten en kleine persoonlijke projecten is het volledig gratis.
Hier is een GitHub Acties workflow die voor alle belangrijke platforms automatisch bouwt:
name: Build Native AOT Binaries
on:
push:
tags:
- 'v*'
jobs:
build-binaries:
name: Build ${{ matrix.runtime }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
runtime: linux-x64
artifact-name: myapp-linux-x64
- os: ubuntu-latest
runtime: linux-arm64
artifact-name: myapp-linux-arm64
- os: windows-latest
runtime: win-x64
artifact-name: myapp-win-x64
- os: macos-latest
runtime: osx-x64
artifact-name: myapp-osx-x64
- os: macos-latest
runtime: osx-arm64
artifact-name: myapp-osx-arm64
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install ARM64 tools (Linux ARM64 only)
if: matrix.runtime == 'linux-arm64'
run: |
sudo apt-get update
sudo apt-get install -y clang zlib1g-dev gcc-aarch64-linux-gnu
- name: Publish
shell: bash
run: |
# Set objcopy for ARM64 cross-compilation
if [ "${{ matrix.runtime }}" = "linux-arm64" ]; then
OBJCOPY_PARAM="-p:ObjCopyName=aarch64-linux-gnu-objcopy"
else
OBJCOPY_PARAM=""
fi
dotnet publish \
-c Release \
-r ${{ matrix.runtime }} \
--self-contained \
--output ./publish/${{ matrix.runtime }} \
-p:PublishAot=true \
-p:PublishTrimmed=true \
-p:StripSymbols=true \
$OBJCOPY_PARAM
- name: Create distribution package
shell: bash
run: |
mkdir -p ./dist
cd ./publish/${{ matrix.runtime }}
# Copy the main executable
cp myapp${{ matrix.file-ext }} ../../dist/
# CRITICAL: Copy native libraries (SQLite and any other native dependencies)
# PublishSingleFile bundles .NET code, but native DLLs remain separate
cp *.dll ../../dist/ 2>/dev/null || true
cp *.so ../../dist/ 2>/dev/null || true
cp *.dylib ../../dist/ 2>/dev/null || true
# Copy config files if needed
cp ../../appsettings.json ../../dist/ || true
cd ../../dist
# Create archive with all files
if [ "${{ runner.os }}" = "Windows" ]; then
7z a -tzip ../${{ matrix.artifact-name }}.zip *
else
tar czf ../${{ matrix.artifact-name }}.tar.gz *
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: |
${{ matrix.artifact-name }}.zip
${{ matrix.artifact-name }}.tar.gz
retention-days: 7
if-no-files-found: ignore
Als de YAML er intimiderend uitziet, dan is dit wat het in het gewone Engels doet:
1. Trigger (on: push: tags)
De workflow draait wanneer je een Git-tag duwt die begint met v (zoals v1.0.0, v2.3.1Dit is de standaard manier om release versies te markeren.
2. Matrixstrategie
Dit is het slimme deel. In plaats van het schrijven van vijf afzonderlijke workflows, definiëren we een matrix van gebouwen:
os (runner machine) en runtime (doelplatform)Dus als je duwt v1.0.0, GitHub gelijktijdig:
3. Stappen in elke bouw
Elk platform bouwt dezelfde stappen:
dotnet publish met AOT-vlaggen voor dat specifieke platform4. Het resultaat
Nadat alle builds voltooid zijn, heb je vijf artefacten (binaires) klaar om te distribueren. Je kunt ze downloaden van de Acties uitvoeren, of een tweede taak gebruiken om een GitHub Release automatisch aan te maken (niet weergegeven in dit knipsel, maar eenvoudig toe te voegen).
Hier is iets dat me uren in de war heeft gebracht: PublishSingleFile=true alleen bundels .NET code. Inheemse bibliotheken zoals SQLite's e_sqlite3.dll Blijf uit elkaar.
Daarom is de stap "Create distribution package" zo belangrijk:
# Copy native libraries - these are NOT included in the main executable
cp *.dll ../../dist/ 2>/dev/null || true # Windows
cp *.so ../../dist/ 2>/dev/null || true # Linux
cp *.dylib ../../dist/ 2>/dev/null || true # macOS
De 2>/dev/null || true onderdeel betekent "als er geen bestanden die overeenkomen met dit patroon, niet falen gewoon doorgaan." Dit laat hetzelfde script werken op alle platforms.
Wat je verspreidt:
myapp.exe + e_sqlite3.dll (samengebundeld in een ZIP)myapp + libe_sqlite3.so (samengebundeld in een tar.gz)myapp + libe_sqlite3.dylib (samengebundeld in een tar.gz)Gebruikers halen het archief uit en voeren het uitvoerbare bestand uit. De native SQLite-bibliotheek zit naast het uitvoerbare bestand en de bundel vindt het automatisch op runtime.
Nota van de workflow_dispatch trigger aan de bovenkant:
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to publish'
required: true
Hiermee kunt u bouwen handmatig triggeren vanaf de webinterface van GitHub zonder een tag te duwen. Nuttig voor het testen van de workflow of het maken van beta builds.
De Linux ARM64 build vereist speciale aandacht. Je hebt cross-compilatie tools nodig en moet de juiste objcopy gereedschap:
# Install tools
sudo apt-get install gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
# Build with objcopy specified
dotnet publish \
-r linux-arm64 \
-p:PublishAot=true \
-p:ObjCopyName=aarch64-linux-gnu-objcopy
Zonder de ObjCopyName parameter, de koppeling faalt met cryptische fouten over onbekende bestandsformaten.
Hier is wat ik bereikt met mijn productie YARP-gebaseerde bot detectie gateway met middleware en SQLite logging. Dit is een echt project dat je kunt downloaden van GitHub.
Dit zijn de werkelijke bestandsgroottes uit mijn GitHub releases, geen theoretische schattingen:
Uitvoerbaar SQLite Native DLL (Total Archive Size) |----------|-----------|-------------------|-------------------| Windows x64 * 9,2MB * +1,7MB * 10,9MB (ZIP) Linux x64, 10,8MB +1.6MB +1.6MB 12,4MB (tar.gz) Linux ARM64, 9.9MB +1.5MB 11,4MB (tar.gz) MacOS Intel, E.E.M. +1.8MB 13,0MB (tar.gz) MacOS ARM64 .8MB +1.7MB +1.7MB 11,5MB (tar.gz)
Vergelijk dit met zelfstandige .NET 9 implementaties op 130-150MB per platform- We hebben het over een... 10-12x reductie in grootte.
Onderverdeling:
Beide bestanden moeten samen worden verspreid, maar ze zijn nog steeds dramatisch kleiner dan traditionele .NET implementaties.
Koude start (eerste verzoek geserveerd) op een bescheiden Linux VPS:
Dit is van groot belang voor:
Inactief geheugen (gateway draait, geen verkeer):
Onder belasting (1000 verzoeken/seconde):
Ondergeheugen betekent:
Batteries.Init()Dit is de #1 fout. Zelfs met de bundel correct genoemd, vergeten te bellen SQLitePCL.Batteries.Init() aan het begin van uw Main methode zal leiden tot runtime crashes.
De oplossing:
public static void Main(string[] args)
{
SQLitePCL.Batteries.Init(); // FIRST LINE
// ... rest of your code
}
Dit is fout nummer twee en het heeft me twee keer geraakt. PublishSingleFile=true bundelt GEEN native SQLite DLL's in uw uitvoerbare bestand. U moet ze verspreiden naast uw uitvoerbare bestand.
Wat gebeurt er als je vergeet:
DllNotFoundExceptionDe oplossing:
Bij het verpakken van uw release, altijd omvatten:
myapp.exe # Your main executable
e_sqlite3.dll # SQLite native library (Windows)
# or libe_sqlite3.so # SQLite native library (Linux)
# or libe_sqlite3.dylib # SQLite native library (macOS)
In uw GitHub Acties of implementatiescripts:
# Copy ALL native libraries from the publish directory
cp *.dll ./dist/ 2>/dev/null || true
cp *.so ./dist/ 2>/dev/null || true
cp *.dylib ./dist/ 2>/dev/null || true
Gebruikers moeten het archief uitpakken en het uitvoerbare bestand uitvoeren. De native library moet in dezelfde map staan.
winsqlite3 AanbiederU zou aanbevelingen kunnen zien om te gebruiken SQLitePCLRaw.provider.winsqlite3 op Windows om de SQLite van het besturingssysteem te gebruiken. Niet doen. Het werkt alleen op Windows, vereist handmatige initialisatie, en breekt cross-platform builds. bundle_e_sqlite3.
Als u gebruik maakt van Entity Framework Core met SQLite, krijgt u trim waarschuwingen (IL2026, IL3050). Deze zijn meestal veilig te onderdrukken voor EF Core's SQLite provider, maar test grondig:
<PropertyGroup>
<NoWarn>$(NoWarn);IL2026;IL3050</NoWarn>
</PropertyGroup>
Beter nog, overweeg het gebruik van Dapper of rauwe ADO.NET met SQLite voor AOT toepassingen zijn meer AOT-vriendelijk.
Op Windows vereist Native AOT Visual Studio's MSVC-linker. Als u buiten een Developer Command Prompt bouwt, krijgt u fouten over vswhere.exe. GitHub Acties behandelen dit automatisch, maar voor lokale builds, gebruik:
Of initialiseer de omgeving in je build script:
& "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\Launch-VsDevShell.ps1" -Arch amd64
dotnet publish -c Release -r win-x64
Native AOT is perfect voor:
Vermijd AOT voor:
Als je dit hele bericht gelezen hebt en gewoon een checklist wilt volgen, hier ga je:
1. Voeg de pakketten toe:
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0" />
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.10" />
2. Configureer uw .csproj voor AOT:
<PublishAot>true</PublishAot>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<InvariantGlobalization>true</InvariantGlobalization>
<PublishSingleFile>true</PublishSingleFile>
<StripSymbols>true</StripSymbols>
<OptimizationPreference>Speed</OptimizationPreference>
3. Initialiseer SQLite aan het begin van uw Main methode:
SQLitePCL.Batteries.Init();
4. Bouwen voor uw doelplatform:
dotnet publish -c Release -r linux-x64 --self-contained
5. Test uw binaire het moet gewoon lopen zonder afhankelijkheden!
SQLite laten werken met Native AOT is niet voor de hand liggend, maar als je eenmaal de magische bezwering kentSQLitePCLRaw.bundle_e_sqlite3 + Batteries.Init()Het is eenvoudig. De uitbetaling is aanzienlijk: kleine binaire bestanden, instant opstarten, en de mogelijkheid om te implementeren naar elk platform zonder runtime afhankelijkheden.
Voor iedereen die CLI-tools, gateways of edge-toepassingen met .NET bouwt, is Native AOT met SQLite nu een realistische optie. De GitHub Acties workflow die hier wordt geleverd automatiseert het gehele multi-platform bouwproces tag een release en je bent klaar.
Als je nieuw bent bij AOT, start dan klein: converteer eerst een simpele CLI tool of utility. Maak het je gemakkelijk met het bouwproces, leer wat waarschuwingen te verwachten, en begrijp de beperkingen. Zodra je de basics omlaag hebt, kun je meer complexe toepassingen aanpakken.
Het .NET ecosysteem is in toenemende mate AOT-vriendelijk. De meeste moderne bibliotheken werken ofwel uit de doos of hebben duidelijke documentatie over AOT ondersteuning. De toekomst is native, en het is sneller dan je denkt.
Ik zet mijn AOT-gecompileerde gateway in om:
Het inzetproces is overal identiek:
Geen "install .NET Runtime" stap. Geen afhankelijkheid hel. Geen versie conflicten. Gewoon uitpakken en uitvoeren.
Voor Docker, mijn Dockerfile is beschamend eenvoudig:
FROM debian:bookworm-slim
# Copy just the two files we need
COPY minigw /app/minigw
COPY libe_sqlite3.so /app/libe_sqlite3.so
WORKDIR /app
RUN chmod +x minigw
EXPOSE 5000
ENTRYPOINT ["./minigw"]
De resulterende afbeelding is ~130MB Een traditionele .NET container zou 200-250MB zijn.
Alles wat ik hier heb laten zien komt van een echt, productieklaar project.
Het project is een minimale YARP reverse proxy met bot detectie middleware die handtekeningen logt naar SQLite. Het demonstreert:
Kloon het, bestudeer het, gebruik het als sjabloon voor je eigen AOT-projecten.
Ga nu iets kleins en snel bouwen.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.