Table of Contents

DataLinq.Memory

DataLinq.Memory is an experimental, read-only backend for generated DataLinq models. It stores explicitly seeded rows in process and executes a small, documented query subset without a SQL provider.

Use it for fast application tests, examples, and transient state when your assertions do not depend on SQL translation, collation, constraints, transactions, or provider-specific behavior. Keep provider-backed tests for those concerns.

Install

Keep the Memory and core package versions aligned:

dotnet add package DataLinq
dotnet add package DataLinq.Memory

The package targets .NET 8, .NET 9, and .NET 10.

Create, seed, and query

Construct the memory database before creating generated mutable rows. Construction binds the generated metadata used by the mutable accessors.

var memory = new MemoryDatabase<MyDatabase>();

memory.Seed<Employee>(
[
    new MutableEmployee
    {
        Id = new EmployeeId(1),
        Name = "Ada"
    },
    new MutableEmployee
    {
        Id = new EmployeeId(2),
        Name = "Grace"
    }
]);

var db = memory.Query();

var names = db.Employees
    .Where(employee => employee.Id != new EmployeeId(2))
    .Select(employee => employee.Name)
    .ToArray();

var ada = memory.Find<Employee>(new EmployeeId(1));

Each table can be seeded once. Seed snapshots and validates the supplied generated mutable rows before publishing the table, so later changes to those mutable objects do not change the memory store. Duplicate keys and invalid values fail the seed instead of publishing partial state.

Find<TModel>(object) supports one non-null primary-key column. It accepts the public model-side key type, including a scalar-converter-backed typed ID, and returns the same cached immutable instance on repeated hits.

Supported query boundary

The 0.9 preview supports a deliberately small capability-gated subset:

  • one generated root table
  • the documented int comparisons and local Contains membership
  • direct Guid and Guid-backed typed-ID equality and inequality
  • &&, ||, and ! over supported predicates
  • one sufficient primary-key ordering with the documented Skip and Take forms
  • direct scalar projection to the selected column's exact model type, including strings, nullable values, Guid, and converter-backed typed IDs
  • Any, Count, Single, SingleOrDefault, and ordered First/FirstOrDefault within the supported shape

Unsupported shapes throw QueryBackendCapabilityException before Memory row work. This includes general LINQ, ThenBy, arbitrary ordering, widened/boxed/computed/anonymous projections, Last, joins, grouping, relation traversal, and terminals after paging.

Deliberate non-features

The preview has no Memory-owned:

  • insert, update, delete, or save operation after seeding
  • transaction, rollback, constraint, or generated-key behavior
  • connection, command, provider, or raw-SQL API
  • persistence, reset, snapshot, or durability contract

DataLinq.Memory is not SQLite :memory:. SQLite in-memory mode is still the real SQLite engine and remains appropriate when a test needs SQL translation, SQLite types, constraints, or transactions.

AOT and browser use

The Memory runtime has no SQL-provider or native-database dependency. The supported generated-model smoke path is exercised under Native AOT, full trimming, and Blazor WebAssembly. That is evidence for the documented preview path, not a claim that arbitrary application code or arbitrary LINQ is AOT-compatible.