Skip to content

[BUG] collection.UpdateMany stores property with DbRef inline instead of as reference #2739

@rklfss

Description

@rklfss

Version
5.0.15

Describe the bug
When using the UpdateMany method on a collection, properties that are marked as DbRef are not stored as reference, but inline.

Code to Reproduce

using LiteDB;

var path = Path.Join(Path.GetTempPath(), "TestDbRef.db");

using var db = new LiteDatabase($"Filename={path};Connection=shared");

var b1 = new B
{
    Id = 1,
};

var b2 = new B
{
    Id = 2,
};

var a1 = new A
{
    Id = 11,
    Bref = b1,
};

db.GetCollection<B>().Upsert(b1);
db.GetCollection<B>().Upsert(b2);
db.GetCollection<A>().Upsert(a1);

// a1 = { "_id": 11, "Bref": { "$id": 1, "$ref": "B" } }

// Update now fails

db.GetCollection<A>()
    .UpdateMany(
        x => new A
        {
            Id = x.Id,
            Bref = b2,
        },
        x => x.Id == 11);

// a1 = { "_id": 11, "Bref": { "_id": 2 } }

// Subsequent selects fail, because the property is not stored as expected.

class A
{
    [BsonId]
    public int Id { get; set; }

    [BsonRef]
    public B? Bref { get; set; }
}

class B
{
    [BsonId]
    public int Id { get; set; }
}

Expected behavior
The translation of the expression consideres the DbRef mapping and stores references with { $id, $ref }.

Additional context
Tracked this down a bit and assume a point in LinqExpressionVisitor.VisitConstant. Here the Serialize method is called on the type of the object itself (here B) instead of the member of our collection type (here Bref of A). Guess the mapper instructions of the collection type should be evaluated everywhere, because this is the type that is expected from the update expression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions