Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use BsonClassMap to map a POCO domain object property as a manual or DBRef reference?

Using BsonClassMap, is it possible to map a domain object reference while keeping the domain object assembly persistent ignorant (changing the public A Reference { get; set; } property to public MongoDBRef Reference{ get; set; } in the sample class B below is not acceptable).

For this case, the referenced object is not a part of the same aggregate, and should not be stored as a nested document.

Is it possible map two domain objects in a relationship like this:

public class A
{
    public Guid Id {get; private set; }
}

public class B
{
    public Guid Id { get; private set; }
    public A Reference { get; set; }
}

Into the following document structure:

// Collection for class A
{ _id: "11111111-1111-1111-1111-111111111111" }

// Collection class B
{ 
    _id: "22222222-2222-2222-2222-222222222222",
    reference_id: "11111111-1111-1111-1111-111111111111"
}

The mapping may look like:

BsonClassMap.RegisterClassMap<A>(cm => 
{
    cm.MapIdProperty(c => c.Id)
        .SetIdGenerator(new GuidGenerator())
        .SetRepresentation(BsonType.String);
}

BsonClassMap.RegisterClassMap<B>(cm => 
{
    cm.MapIdProperty(c => c.Id)
        .SetIdGenerator(new GuidGenerator())
        .SetRepresentation(BsonType.String);

    // How do I map the B.Reference to a manual reference (like 
    // the sample doc structure above) or possibly as a DBRef?
}

So, without changing the model, how do I map the Reference property to object A, from object B as either a DBRef or as a manual references (as in my sample document structure above)?

Is this possible using BsonClassMap? Or in order to use BsonClassMap and keep my domain assembly persistent ignorant, do I need to change the model to something like:

public class A
{
    public Guid Id {get; private set; }
}

public class B
{
    public Guid Id { get; private set; }
    public Guid ReferenceId { get; set; } // Don't reference the object directly,
                                          // just store the Guid to the 
                                          // referenced object.
}
like image 441
Geoff Avatar asked Feb 18 '13 21:02

Geoff


1 Answers

I posed this same question to the mongodb-csharp user group and got a response from craiggwilson:

You'll need to change your ReferenceProperty to ReferencePropertyId. We do not support lazy-loading (or eager-loading) of referenced documents.

Since A is not the aggregate for B, then this actually makes more sense when discussing in these terms. Generally, it is unnecessary for a referenced aggregate (B) to be loaded in order to process the referencing aggregate (A). It might be that you do indeed need some information from B. In this case, think about denormalizing a little and creating a true entity (BSummary) whose aggregate is A. This would make sense if some of the summary information is immutable or changes infrequently.

like image 103
Geoff Avatar answered Oct 21 '22 04:10

Geoff