#2912·LiteDB

Typed queries disagree with CLR defaults for missing BSON fields

Author: JKamskerCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbugseverity: highpriority: P3

Typed queries and in-memory LINQ disagree when a persisted BSON field is absent and materialization supplies a CLR default. Track that concrete behavior separately from #2093, whose original model, predicate, sample document and exact version were never supplied. This reproduction does not establish the cause of that original report.

Reproduction

csharp
using System.Linq;
using LiteDB;

using var db = new LiteDatabase(":memory:");
db.GetCollection("users").Insert(new BsonDocument { ["_id"] = 41 });
var users = db.GetCollection<User>("users");

var inMemory = users.FindAll().Where(x => x.Removed == false)
    .Select(x => x.Id).ToArray(); // [41]
var inDatabase = users.Find(x => x.Removed == false)
    .Select(x => x.Id).ToArray(); // []

public class User
{
    public int Id { get; set; }
    public bool Removed { get; set; }
}

The stored document lacks Removed. Materialization leaves it at false, while the BSON query compares an absent/null value against false and rejects it. Fully persisted controls match across both evaluation paths.

Preserved executable evidence

The original fixture is retained unchanged as LiteDB.Tests/Issues/Issue2093_Tests.cs. The historical filename is retained to preserve the frozen test identity and known-failure mappings; these tests now track this issue, not a confirmed reproduction of #2093.

The fixture independently seeds BSON, closes/reopens the database, verifies field absence and raw encodings, and checks renamed fields, enum string/integer storage, dates and an ID-query control. Latest sweep evidence: two missing-field cases fail; two fully persisted controls pass.

bash
dotnet test LiteDB.Tests -c Release -f net8.0 -p:TestingEnabled=true \
  --settings tests.runsettings --filter FullyQualifiedName~Issue2093_

Design questions before implementation

  • Decide whether typed queries should retain stored-BSON semantics or support explicitly configured defaults for absent fields. Do not silently redefine raw BSON queries.
  • A CLR type default alone is insufficient: public bool Removed { get; set; } = true;, constructors, custom factories and deserialization hooks can produce a different value.
  • Distinguish absent fields from explicitly stored null, false and true. Assess indexed/unindexed consistency and compatibility with existing queries and data.
  • If opt-in defaults are chosen, define how they are configured and how queries/indexes interpret them; preserve controls for constructor-initialized values and existing documents.

This is separate design work, outside the current manual bug-fix sweep. The retained parity assertions demonstrate the mismatch; they do not settle the final compatibility contract.