IRI.Maptor.Ket.SqlitePersistence 2.8.11

dotnet add package IRI.Maptor.Ket.SqlitePersistence --version 2.8.11
                    
NuGet\Install-Package IRI.Maptor.Ket.SqlitePersistence -Version 2.8.11
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="IRI.Maptor.Ket.SqlitePersistence" Version="2.8.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="IRI.Maptor.Ket.SqlitePersistence" Version="2.8.11" />
                    
Directory.Packages.props
<PackageReference Include="IRI.Maptor.Ket.SqlitePersistence" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add IRI.Maptor.Ket.SqlitePersistence --version 2.8.11
                    
#r "nuget: IRI.Maptor.Ket.SqlitePersistence, 2.8.11"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package IRI.Maptor.Ket.SqlitePersistence@2.8.11
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=IRI.Maptor.Ket.SqlitePersistence&version=2.8.11
                    
Install as a Cake Addin
#tool nuget:?package=IRI.Maptor.Ket.SqlitePersistence&version=2.8.11
                    
Install as a Cake Tool

IRI.Maptor.Ket.SqlitePersistence

SQLite-based geospatial format support for the Maptor library.

Overview

This package provides support for reading SQLite-based geospatial formats:

  • MBTiles - Tile-based map storage format for offline mapping
  • OGC GeoPackage - Universal geospatial data container (vector features and raster tiles)

Both formats are cross-platform compatible and work seamlessly with .NET 8, MAUI, and mobile platforms (Android, iOS, Windows, macOS).

Supported Formats

πŸ—ΊοΈ MBTiles

MBTiles is a specification for storing tiled map data in SQLite databases for immediate use and for transfer. It's optimized for offline mapping applications.

Features:

  • Raster tiles (PNG, JPEG, WebP)
  • Vector tiles (PBF)
  • Metadata support (name, description, bounds, attribution)
  • TMS (Tile Map Service) coordinate scheme
  • Efficient storage with SQLite compression

Specification: MBTiles Spec

πŸ“¦ GeoPackage (GPKG)

GeoPackage is an OGC standard for geospatial data exchange. It can store multiple types of data in a single file:

  • Vector features (points, lines, polygons)
  • Raster tiles and coverage data
  • Attributes and metadata
  • Multiple layers in a single file

Features:

  • OGC standard format
  • Cross-platform compatibility
  • Rich metadata support
  • Spatial indexing (R-Tree)
  • Multiple coordinate reference systems

Specification: OGC GeoPackage

Installation

dotnet add package IRI.Maptor.Ket.SqlitePersistence

Usage Examples

MBTiles - Reading Tiles

using IRI.Maptor.Ket.SqlitePersistence.MbTiles;
using IRI.Maptor.Sta.Common.Primitives;

// Create and open MBTiles reader
using var reader = new MbTilesReader("path/to/map.mbtiles");
reader.Open();

// Get metadata
var metadata = reader.Metadata;
Console.WriteLine($"Name: {metadata?.Name}");
Console.WriteLine($"Format: {metadata?.Format}");
Console.WriteLine($"Zoom Range: {metadata?.MinZoom} - {metadata?.MaxZoom}");
Console.WriteLine($"Bounds: {metadata?.Bounds}");

// Get available zoom levels
var zoomLevels = reader.GetZoomLevels();
Console.WriteLine($"Available zooms: {string.Join(", ", zoomLevels)}");

// Get a specific tile (zoom, column, row in TMS scheme)
byte[]? tileData = reader.GetTile(zoom: 10, column: 512, row: 384);
if (tileData != null)
{
    // Save tile to file or display
    File.WriteAllBytes("tile.png", tileData);
}

// Get tile count
long totalTiles = reader.GetTileCount();
long tilesAtZoom10 = reader.GetTileCount(zoomLevel: 10);

// Get bounding box
BoundingBox? bbox = reader.GetBoundingBox();

MBTiles - Using Data Source

using IRI.Maptor.Ket.SqlitePersistence.MbTiles;
using IRI.Maptor.Sta.Common.Primitives;

// Create MBTiles data source (for use with map viewers)
using var dataSource = new MbTilesDataSource("path/to/map.mbtiles");

// Get tiles for a specific area and map scale
var boundingBox = new BoundingBox(
    xMin: -74.01, yMin: 40.70,  // New York City area
    xMax: -73.99, yMax: 40.72
);

double mapScale = 10000; // Adjust based on your zoom level

var tiles = dataSource.GetTiles(boundingBox, mapScale);

Console.WriteLine($"Loaded {tiles.Count} tiles");

foreach (var tile in tiles)
{
    Console.WriteLine($"Tile: {tile.ImageBytes.Length} bytes, Bounds: {tile.BoundingBox}");
}

// Get available zoom levels
var availableZooms = dataSource.GetAvailableZoomLevels();

// Get specific tile
byte[]? specificTile = dataSource.GetTile(zoom: 10, column: 512, row: 384);

GeoPackage - Reading Vector Features

using IRI.Maptor.Ket.SqlitePersistence.GeoPackage;
using IRI.Maptor.Sta.Common.Primitives;

// Create and open GeoPackage vector reader
using var reader = new GpkgVectorReader("path/to/data.gpkg");
reader.Open();

// Get all feature layers
var layers = reader.GetFeatureLayers();
foreach (var layer in layers)
{
    Console.WriteLine($"Layer: {layer.TableName}");
    Console.WriteLine($"  Type: {layer.DataType}");
    Console.WriteLine($"  Description: {layer.Description}");
    Console.WriteLine($"  Bounds: ({layer.MinX}, {layer.MinY}) to ({layer.MaxX}, {layer.MaxY})");
}

// Get geometry column information
var geometryInfo = reader.GetGeometryColumnInfo("countries");
Console.WriteLine($"Geometry Column: {geometryInfo?.ColumnName}");
Console.WriteLine($"Geometry Type: {geometryInfo?.GeometryTypeName}");
Console.WriteLine($"SRID: {geometryInfo?.SrsId}");

// Read all features from a layer
var features = reader.ReadFeatures("countries");
Console.WriteLine($"Loaded {features.Count} features");

foreach (var feature in features)
{
    Console.WriteLine($"Geometry Type: {feature.TheGeometry?.Type}");
    
    // Access attributes
    if (feature.Attributes != null)
    {
        foreach (var attr in feature.Attributes)
        {
            Console.WriteLine($"  {attr.Key}: {attr.Value}");
        }
    }
}

// Read features within a bounding box
var bbox = new BoundingBox(-10, 35, 5, 45); // Approximate bounds for Western Europe
var filteredFeatures = reader.ReadFeatures("countries", bbox);

// Get feature count
long featureCount = reader.GetFeatureCount("countries");

// Get spatial reference systems
var srsList = reader.GetSpatialReferenceSystems();

GeoPackage - Using Vector Data Source

using IRI.Maptor.Ket.SqlitePersistence.GeoPackage;
using IRI.Maptor.Sta.Common.Primitives;

// Create GeoPackage vector data source
using var dataSource = new GeoPackageDataSource("path/to/data.gpkg", "countries");

// Get all features as FeatureSet
var featureSet = dataSource.GetAsFeatureSet(null);
Console.WriteLine($"Total features: {featureSet.Features.Count}");
Console.WriteLine($"SRID: {featureSet.Srid}");

// Get features within a bounding box
var bbox = new BoundingBox(-10, 35, 5, 45);
var filteredFeatureSet = dataSource.GetAsFeatureSet(bbox);

// Search features by text
var searchResults = dataSource.Search("Germany");

// Get layer metadata
var metadata = dataSource.LayerMetadata;
Console.WriteLine($"Layer: {metadata?.TableName}");
Console.WriteLine($"Description: {metadata?.Description}");

// Get geometry column info
var geomCol = dataSource.GeometryColumn;
Console.WriteLine($"Geometry: {geomCol?.GeometryTypeName}");

// Get feature count
long count = dataSource.GetFeatureCount();

GeoPackage - Reading Tile Layers

using IRI.Maptor.Ket.SqlitePersistence.GeoPackage;

// Create and open GeoPackage tile reader
using var reader = new GpkgTileReader("path/to/tiles.gpkg");
reader.Open();

// Get all tile layers
var tileLayers = reader.GetTileLayers();
foreach (var layer in tileLayers)
{
    Console.WriteLine($"Tile Layer: {layer.TableName}");
    Console.WriteLine($"  Description: {layer.Description}");
}

// Get tile matrix set (pyramid information)
var tileMatrixSet = reader.GetTileMatrixSet("satellite_tiles");
Console.WriteLine($"SRS ID: {tileMatrixSet?.SrsId}");
Console.WriteLine($"Bounds: {tileMatrixSet?.MinX},{tileMatrixSet?.MinY} to {tileMatrixSet?.MaxX},{tileMatrixSet?.MaxY}");

// Get all zoom levels (tile matrices)
var matrices = reader.GetTileMatrices("satellite_tiles");
foreach (var matrix in matrices)
{
    Console.WriteLine($"Zoom {matrix.ZoomLevel}: {matrix.MatrixWidth}x{matrix.MatrixHeight} tiles");
    Console.WriteLine($"  Tile size: {matrix.TileWidth}x{matrix.TileHeight} pixels");
}

// Get a specific tile
byte[]? tile = reader.GetTile("satellite_tiles", zoom: 10, column: 512, row: 384);

// Get available zoom levels
var zooms = reader.GetZoomLevels("satellite_tiles");

// Get tile count
long totalTiles = reader.GetTileCount("satellite_tiles");
long tilesAtZoom = reader.GetTileCount("satellite_tiles", zoomLevel: 10);

// Get zoom range
var (minZoom, maxZoom) = reader.GetZoomRange("satellite_tiles") ?? (0, 0);

GeoPackage - Using Tile Data Source

using IRI.Maptor.Ket.SqlitePersistence.GeoPackage;
using IRI.Maptor.Sta.Common.Primitives;

// Create GeoPackage tile data source
using var dataSource = new GeoPackageTileDataSource("path/to/tiles.gpkg", "satellite_tiles");

// Get tiles for a specific area and map scale
var bbox = new BoundingBox(-74.01, 40.70, -73.99, 40.72); // NYC
double mapScale = 10000;

var tiles = dataSource.GetTiles(bbox, mapScale);
Console.WriteLine($"Loaded {tiles.Count} tiles");

// Get available zoom levels
var zoomLevels = dataSource.GetAvailableZoomLevels();

// Get specific tile
byte[]? tile = dataSource.GetTile(zoom: 10, column: 512, row: 384);

// Get metadata
var metadata = dataSource.LayerMetadata;
var tileMatrixSet = dataSource.TileMatrixSet;

// Get zoom range
var zoomRange = dataSource.GetZoomRange();
Console.WriteLine($"Zoom range: {zoomRange?.minZoom} - {zoomRange?.maxZoom}");

Coordinate Systems

MBTiles

  • Uses TMS (Tile Map Service) coordinate scheme
  • Y-axis origin at bottom-left (row 0 is at the bottom)
  • Tiles are typically in Web Mercator (EPSG:3857)
  • Bounds are stored in WGS84 (EPSG:4326) format

GeoPackage

  • Uses XYZ tile scheme for tiles (Y-axis origin at top-left)
  • Supports multiple coordinate reference systems (CRS)
  • Check srs_id in metadata for the coordinate system
  • Common systems:
    • 4326 - WGS84 (Geographic)
    • 3857 - Web Mercator
    • 900913 - Google Web Mercator (legacy)

Converting Between Tile Schemes

// Converting from XYZ to TMS
int xyzY = 384;
int zoom = 10;
int maxTileIndex = (1 << zoom) - 1; // 2^zoom - 1
int tmsY = maxTileIndex - xyzY;

// Converting from TMS to XYZ
int tmsYValue = 639;
int xyzYValue = maxTileIndex - tmsYValue;

Async Operations

Both readers support async operations:

// MBTiles async
using var mbReader = new MbTilesReader("map.mbtiles");
await mbReader.OpenAsync();
byte[]? tile = await mbReader.GetTileAsync(10, 512, 384);

// GeoPackage async
using var gpReader = new GpkgVectorReader("data.gpkg");
await gpReader.OpenAsync();

using var tileReader = new GpkgTileReader("tiles.gpkg");
await tileReader.OpenAsync();
byte[]? gpTile = await tileReader.GetTileAsync("layer", 10, 512, 384);

Platform Support

βœ… .NET 8+
βœ… MAUI (Android, iOS, Windows, macOS)
βœ… Desktop (Windows, Linux, macOS)
βœ… Mobile (Android, iOS)

Dependencies

  • Microsoft.Data.Sqlite.Core - Modern SQLite ADO.NET provider
  • SQLitePCLRaw.bundle_e_sqlite3 - Native SQLite binaries for all platforms
  • IRI.Maptor.Sta.Persistence - Maptor persistence abstractions
  • IRI.Maptor.Sta.Spatial - Maptor spatial types and algorithms
  • IRI.Maptor.Sta.Ogc - OGC standard implementations

Performance Tips

  1. Use spatial indexes: Both formats support spatial indexing (R-Tree) for fast queries
  2. Batch operations: When reading multiple tiles, consider parallel processing
  3. Connection pooling: Reuse readers/data sources instead of creating new ones
  4. Bounding box queries: Use bounding box filtering to limit data transfer
  5. Appropriate zoom levels: Request tiles at appropriate zoom levels for your map scale

Validation

// Validate MBTiles schema
using var mbReader = new MbTilesReader("map.mbtiles");
mbReader.Open();
bool isMbTilesValid = mbReader.ValidateSchema();

// Validate GeoPackage schema
using var gpReader = new GpkgVectorReader("data.gpkg");
gpReader.Open();
bool isGpkgValid = gpReader.ValidateSchema();

Error Handling

try
{
    using var reader = new MbTilesReader("map.mbtiles");
    reader.Open();
    
    var tile = reader.GetTile(10, 512, 384);
    if (tile == null)
    {
        Console.WriteLine("Tile not found");
    }
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"File not found: {ex.Message}");
}
catch (InvalidOperationException ex)
{
    Console.WriteLine($"Invalid operation: {ex.Message}");
}
catch (SqliteException ex)
{
    Console.WriteLine($"SQLite error: {ex.Message}");
}

Best Practices

  1. Dispose properly: Always use using statements or call Dispose() to release resources
  2. Check for null: Tiles and features may not exist, always check for null
  3. Validate files: Use ValidateSchema() to ensure files are valid before processing
  4. Handle exceptions: Wrap file operations in try-catch blocks
  5. Use async for UI apps: Use async methods in UI applications to avoid blocking

Contributing

Contributions are welcome! Please see the Maptor Contributing Guide.

License

This package is part of the Maptor library and is licensed under the MIT License.

Resources

Support

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.8.11 385 11/19/2025
2.8.11-alpha 376 11/19/2025
2.8.10 132 11/8/2025
2.8.10-alpha 125 11/8/2025
2.8.9-alpha 113 11/1/2025