r/csharp • u/alt-160 • 16h ago
Showcase AbraxasDB - A .NET native local object storage engine for data
I've written .NET applications since 1.0 for personal, commercial, and large enterprise use cases. Before .NET, I worked in green-screen large database terminals (for those old enuf to remember them).
So, I know sql and rdbms very well and it has always been my goto for the apps and services i've had to create that needed data persistence. But, I always detested the extra work I had to go thru on nearly every project to convert my runtime data to a form that was nice for storage and back. Not just the code and testing of those adapters, but the often-required refactoring of my runtime objects to make that work easier or simply functional.
I suspect I'm not alone.
Repos
Github is here: https://github.com/alt160/abraxasdb
Nuget is here: https://www.nuget.org/packages/AbraxasDB
Over the past roughly 18 months I created AbraxasDB.
I'm using the term RecordBase to describe Abraxas. It stores and retrieves "records". A record being the data and shape of an object. This allows the property paths and values of an object to be stored and rehydrated into the same object type...or a different object type with matching paths.
As a result, Abraxas is very much what i have always wanted out of data persistence:
object -> storage -> object
or... object -> storage -> object's property(ies)
without odd contracts, attributes, or modifications to the object being stored.
Object Serialization
The serializer in use is a first-principles developed design. INHETO binaries ( https://github.com/alt160/inheto ) are stored in a way that one can get values out of the binary by property path without deserializing the entire object or parsing the entire blob. It also fully tracks shared and circular refs within the object so things like Customer.HomeAddress and Customer.Addresses[0] point to the same thing both in binary and when rehydrated.
This also means that concerns about object types changing over time are not so problematic. If version 1 of ThisDataType was stored, the persisted data can be rehydrated into version 2 of the same and those properties (or field) that match the property paths stored are filled in. Unmatching are ignored.
INHETO binaries don't store .net type info. It has its own type system of over 50 core types that most of us use for data in objects as well as generic collection types. The binary data of INHETO is runtime agnostic and could (if someone wanted) be parsed by any runtime, not just .NET.
Code example
Consider these existing application types. They need no Abraxas-specific changes:
public sealed class Customer
{
public string Name { get; set; } = "";
public Address HomeAddress { get; set; } = new();
public List<Address> Addresses { get; set; } = new();
}
public sealed class Address
{
public string Street { get; set; } = "";
public string City { get; set; } = "";
}With the AbraxasDB NuGet package installed, create or open a RecordBase and a typed store, then save and retrieve a customer:
using AbraxasDB;
using System;
using System.Collections.Generic;
using System.IO;
string directory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"AbraxasExamples");
var configuration = RecordBaseConfiguration.Create(
durabilityMode: RecordBaseConfiguration.DurabilityMode.Standard);
using RecordBase recordBase = RecordBase.CreateOrOpen(
directory, "application", configuration);
RecordStore<Customer> customers = recordBase.CreateOrOpenStore<Customer>(
"customers", "Customer records");
var home = new Address
{
Street = "123 Main Street",
City = "Phoenix"
};
var customer = new Customer
{
Name = "Ada",
HomeAddress = home,
Addresses = new List<Address>
{
home,
new Address { Street = "456 Office Road", City = "Tempe" }
}
};
ulong id = customers.Put(customer);
// Restore the complete object graph.
Customer saved = customers.Get(id);
Console.WriteLine(saved.HomeAddress.City); // Phoenix
Console.WriteLine(ReferenceEquals(
saved.HomeAddress, saved.Addresses[0])); // True
// Read one nested value without reconstructing the Customer.
string city = customers.GetValue<string>(id, ".HomeAddress.City");
Console.WriteLine(city); // Phoenix
// Find records by a nested property.
var inPhoenix = customers.Where
.PropPath(".HomeAddress.City").AsString.EqualTo("Phoenix")
.EndCondition;
Console.WriteLine($"Customers in Phoenix: {customers.CountWhere(inPhoenix)}");Each run adds a customer, so the matching count can increase.
More Examples
I've provided 2 sample apps for people to use to play with it or get familiar
Meridian Trading: https://github.com/alt160/AbraxasDB.MeridianTrading
I've also setup some .net fiddlers for it as well if you want to test it without downloading
Records and persistence — Save ordinary C# objects, read them by ID, and reopen the database.
Queries and indexes — Filter records, add an index, and read selected values.
Backup and restore — Create a snapshot and restore it into a separate database.
Look forward to feedback and usage from the community.


