Library for interacting with Geopackages.
$ dotnet add package MapPiloteGeopackageHelperModern .NET library for creating, reading, and bulk-loading GeoPackage (GPKG) data using SQLite and NetTopologySuite.
Latest Release: v1.2.2 - Fixed ORDER BY clause in ReadFeaturesAsync (ASC/DESC sorting now works correctly)
Note that in version 1.2.1 I have split the repository on github into two, hope it simplifies understanding:
// Create/open GeoPackage with fluent API
using var geoPackage = await GeoPackage.OpenAsync("data.gpkg", srid: 3006);
// Create layer with schema
var layer = await geoPackage.EnsureLayerAsync("cities", new Dictionary<string, string>
{
["name"] = "TEXT",
["population"] = "INTEGER",
["area_km2"] = "REAL"
});
// Bulk insert with progress
var progress = new Progress<BulkProgress>(p =>
Console.WriteLine($"Progress: {p.PercentComplete:F1}%"));
await layer.BulkInsertAsync(features,
new BulkInsertOptions(BatchSize: 1000, CreateSpatialIndex: true),
progress);
// Query with async streaming and ORDER BY support
await foreach (var city in layer.ReadFeaturesAsync(
new ReadOptions(
WhereClause: "population > 100000",
OrderBy: "population DESC", // ? Fixed in v1.2.2
Limit: 10)))
{
Console.WriteLine($"City: {city.Attributes["name"]} - {city.Attributes["population"]} people");
}
// Count and delete operations
var count = await layer.CountAsync("population < 50000");
var deleted = await layer.DeleteAsync("population < 10000");
Enable WAL (Write-Ahead Logging) mode for better concurrency and performance:
// Create GeoPackage with WAL mode enabled
CMPGeopackageCreateHelper.CreateGeoPackage(
"data.gpkg",
srid: 3006,
walMode: true,
onStatus: Console.WriteLine);
// WAL mode with default SRID (3006)
CMPGeopackageCreateHelper.CreateGeoPackage("data.gpkg", walMode: true);
// Backward compatible - existing code continues to work
CMPGeopackageCreateHelper.CreateGeoPackage("data.gpkg", 3006);
PRAGMA journal_mode = WAL| Feature | Description | Example |
|---|---|---|
| Async/Await | Proper async support with CancellationToken | await layer.BulkInsertAsync(...) |
| Fluent API | Chain operations naturally | GeoPackage.OpenAsync().EnsureLayerAsync() |
| Progress Reporting | Track long-running operations | IProgress<BulkProgress> |
| Options Objects | Clean configuration, no parameter soup | BulkInsertOptions(BatchSize: 1000) |
| Streaming | IAsyncEnumerable for large datasets | await foreach (var item in ...) |
| Rich Queries | WHERE, LIMIT, ORDER BY support | ReadOptions(OrderBy: "score DESC") |
| Conflict Handling | Insert policies (Abort/Ignore/Replace) | ConflictPolicy.Ignore |
| CRUD Operations | Count, Delete with conditions | await layer.DeleteAsync("status = 'old'") |
| WAL Mode | Write-Ahead Logging for concurrency | CreateGeoPackage(path, walMode: true) |
// One-liner with progress and options
using var gp = await GeoPackage.OpenAsync("data.gpkg");
var layer = await gp.EnsureLayerAsync("places", schema);
await layer.BulkInsertAsync(features, options, progress);// Multi-step process with optional WAL mode
CMPGeopackageCreateHelper.CreateGeoPackage(path, srid, walMode: true);
GeopackageLayerCreateHelper.CreateGeopackageLayer(path, name, schema);
CGeopackageAddDataHelper.BulkInsertFeatures(path, name, features);// Basic creation
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg");
// With custom SRID
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg", srid: 4326);
// With status callback
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg", onStatus: Console.WriteLine);
// With SRID and callback
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg", 4326, Console.WriteLine);
// With WAL mode (default SRID)
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg", walMode: true);
// Full control: SRID + WAL + callback
CMPGeopackageCreateHelper.CreateGeoPackage("path.gpkg", 4326, true, Console.WriteLine);ReadFeaturesAsync now works correctly with both ASC and DESCdotnet add package MapPiloteGeopackageHelperFluentApiExample projectMapPiloteGeopackageHelperSchemaBrowser for unknown filesMapPiloteGeopackageHelperHelloWorldOpen the generated .gpkg files in QGIS, ArcGIS, or any GIS software!