JackcessDotNet 1.2.2
dotnet add package JackcessDotNet --version 1.2.2
NuGet\Install-Package JackcessDotNet -Version 1.2.2
<PackageReference Include="JackcessDotNet" Version="1.2.2" />
<PackageVersion Include="JackcessDotNet" Version="1.2.2" />
<PackageReference Include="JackcessDotNet" />
paket add JackcessDotNet --version 1.2.2
#r "nuget: JackcessDotNet, 1.2.2"
#:package JackcessDotNet@1.2.2
#addin nuget:?package=JackcessDotNet&version=1.2.2
#tool nuget:?package=JackcessDotNet&version=1.2.2
JackcessDotNet
Pure .NET 8 library for reading and writing Microsoft Access (.mdb / .accdb) files.
No ODBC, no ACE drivers, no native dependencies — runs anywhere .NET 8 runs
(Windows, Linux, macOS, containers).
This is a C# port of the spannm/jackcess Java
project (a maintained fork of the original Jackcess
by James Ahlborn). The upstream Java project remains the source of truth for the Jet
file format; this port tracks its behaviour and reuses its test corpus for
verification.
Install
dotnet add package JackcessDotNet
Quick start
using JackcessDotNet;
// Open an existing .mdb / .accdb (auto-detects version)
using var db = Database.Open("Northwind.mdb");
foreach (var name in db.ListTables())
Console.WriteLine(name);
var customers = db.GetTable("Customers");
foreach (var row in customers.NewCursor())
Console.WriteLine($"{row["CustomerID"]} {row["CompanyName"]}");
// Create a new database, define a schema, insert rows
using var fresh = Database.Create("MyData.mdb", JetVersion.Jet4);
var people = fresh.CreateTable("People", new[]
{
new ColumnBuilder("Id", DataType.Long).Build(),
new ColumnBuilder("Name", DataType.Text).MaxLength(50).Build(),
}, primaryKey: "Id");
people.Insert(new Row { ["Id"] = 1, ["Name"] = "Alice" });
Opening password-protected files
// Jet RC4 (.mdb, Access 97 / 2000–2003)
using var db = Database.Open("Confidential.mdb", "passw0rd");
// .accdb encryption — Agile (Office 2010+), ECMA Standard (Office 2007),
// RC4 CryptoAPI (Office 2002–2003), or Non-Standard AES — all auto-detected
// from the EncryptionInfo header.
using var db = Database.Open("Confidential.accdb", "passw0rd");
// Inspect which scheme the codec picked (useful when triaging an unfamiliar file).
byte[] page0 = File.ReadAllBytes("Confidential.accdb").Take(4096).ToArray();
var codec = OfficeCryptCodecHandler.FromDbHeader(page0, "passw0rd");
Console.WriteLine(codec?.Scheme); // → "Agile Encryption (Office 2010+)"
Wrong passwords throw UnauthorizedAccessException before any data page is
parsed — no cryptic "page X corrupt" errors.
Composite (multi-column) primary keys
db.CreateTable("Orders", new[]
{
new ColumnBuilder("CustomerId", DataType.Long).Build(),
new ColumnBuilder("OrderId", DataType.Long).Build(),
new ColumnBuilder("Total", DataType.Money).Build(),
}, primaryKeyColumns: new[] { "CustomerId", "OrderId" });
Up to 10 columns per composite key (Jet's hard limit). The single-column
primaryKey: overload still works for the common case.
Foreign-key enforcement on insert (opt-in)
using var db = Database.Open("Northwind.mdb");
db.EnforceForeignKeys = true; // default: false
// MSysRelationships drives validation. Any Insert whose FK column doesn't
// match an existing parent row throws InvalidOperationException.
orders.Insert(new Row { ["CustomerID"] = "INVALID", ... });
// ^ throws "Foreign-key violation in
// relationship 'CustomersOrders'..."
Null FK values are allowed (SQL semantics). Restrict-only — no cascade.
Importing from DataTable, DataSet, or IEnumerable<T>
Skip the schema boilerplate — the importer infers columns from the source type:
using var db = DatabaseImporter.CreateFromDataTable("out.mdb", myDataTable);
// or add into an existing database
db.ImportTable(otherDataTable, tableName: "Extra", primaryKey: "Id");
db.ImportTables(myDataSet);
db.ImportTable<Customer>(customers, primaryKey: "Id");
// Append rows into a pre-existing table (instead of failing):
db.ImportTable(moreRows, options: new ImportOptions { AppendIfExists = true });
POCO mapping respects [Key], [Column("X")], [MaxLength], [NotMapped],
and [DatabaseGenerated(Identity)]. Long strings (>255 chars) auto-promote
to Memo; large byte arrays (>255 bytes) to OLE. Unmappable types can fall
back to Memo via ImportOptions.FallbackUnmappableToString = true.
Exporting back
DataTable dt = db.ExportToDataTable("Customers");
DataSet ds = db.ExportToDataSet();
IEnumerable<Customer> cs = db.ExportToCollection<Customer>("Customers");
The IEnumerable<T> path is lazy via yield, so Take(n) stops early without
materialising the whole table.
Status
| Feature | Status |
|---|---|
| Read Jet 3 (Access 97) / Jet 4 (Access 2000–2003) | ✅ |
Read ACE 12 / 14 / 16 / 17 (.accdb) |
✅ |
Create new .mdb files (Jet 4 / Jet 3) |
✅ |
| Row CRUD + B-tree indexes (single-column PK) | ✅ |
| Memo / OLE long values | ✅ |
| PropertyMap & MSysRelationships | ✅ |
Password-protected .mdb (Jet RC4 codec) |
✅ |
Password-protected .accdb (Agile Encryption, Office 2010+) |
✅ Read + write¹ |
Password-protected .accdb (ECMA Standard Encryption, Office 2007) |
✅ Read + write |
Password-protected .accdb (RC4 CryptoAPI, Office 2002–2003) |
✅ Read + write |
Password-protected .accdb (Non-Standard AES, compat mode 0) |
✅ Read + write |
Password-protected .accdb (Extensible Encryption) |
❌ External CSP — non-portable |
| Multi-column primary keys | ✅ |
| Foreign-key enforcement on insert (opt-in) | ✅ Restrict-only |
Queries (MSysQueries) |
❌ Not yet |
¹ Agile write doesn't recompute the DataIntegrity HMAC, so files modified
through this library round-trip cleanly through Database.Open(path, password)
but Office Access may flag a stale integrity hash. Matches the upstream
jackcess-encrypt limitation.
Type round-trip cheat sheet
| CLR type | Jet column | Notes |
|---|---|---|
bool |
Boolean |
|
byte |
Byte |
|
short/ushort |
Int (16-bit) |
both come back as short |
int/uint |
Long (32-bit) |
both come back as int |
long/ulong |
Long (32-bit) |
truncated to 32 bits |
float/double |
Float/Double |
|
decimal |
Money |
4-decimal precision; use Numeric for more |
DateTime |
ShortDateTime |
Kind is dropped |
DateTimeOffset |
ShortDateTime |
stored as UTC |
Guid |
Guid |
|
string ≤255 |
Text |
|
string >255 |
Memo |
auto-promoted on MaxLength |
byte[] ≤255 |
Binary |
|
byte[] >255 |
Ole |
auto-promoted on MaxLength |
Nullable<T> |
underlying T |
|
enum |
underlying type | round-trips back to the enum on read |
Version history
See CHANGELOG.md — also shipped inside the .nupkg.
Credits
This project would not exist without the years of reverse-engineering work
done by James Ahlborn (original Jackcess) and Markus Spann (maintained fork
at spannm/jackcess). The Jet binary
format is documented effectively only through their Java source.
License
Apache License 2.0 — same as the upstream Jackcess project.
| Product | Versions 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. |
-
net8.0
- System.Text.Encoding.CodePages (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
1.2.2 — Adds a package icon (jackcess.png). Same metadata + SourceLink
improvements introduced in 1.2.1 (PackageProjectUrl, RepositoryUrl,
Microsoft.SourceLink.GitHub, README badges). No library code changes
vs. 1.2.0; see CHANGELOG.md.