-
Type:
New Feature
-
Resolution: Won't Do
-
Priority:
Major - P3
-
None
-
Affects Version/s: 2.2.4, 2.3.0-beta1
-
Component/s: Serialization
-
None
-
None
-
None
-
None
-
None
-
None
-
None
I am trying to implement suitable reference container for objects, located in separate collections. For example,
//some interface to specify persistent objects with Id public interface IPersistentObject { long Id { get; } } //and two entities mapped to separate collections public class Sample: IPersistentObject { public long Id { get; set; } } public class SampleWithReference: IPersistentObject { public long Id { get; set; } public Ref<Sample> Parent { get; set; } }
Using described entities.
var sample = new Sample() {Id: 32412132}; var sampleWithRef = new SampleWithReference() {Id: 5635634}; sampleWithRef.Parent.Set(sample); //and save both objects
It results in the following DB record for SampleWithReference object:
{ "Id": 5635634, "Parent": 32412132 }
The reference container itself:
//here is the reference container public class Ref<T> : IPersistentObject, IEquatable<long>, IEqualityComparer<long> where T : IPersistentObject, new() { public long Id { get; private set; } private T _Object; public T Get() { return _Object; } public void Set(T value) { _Object = value; Id = value == null ? 0L : value.Id; } //IEquatable and IEqualityComparer memebers implementation here }
And serializer for it:
public class RefSerializer<T> : SerializerBase<Ref<T>> where T : IPersistentObject, new() { public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Ref<T> value) { long v = value; context.Writer.WriteInt64(v); } public override Ref<T> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var id = context.Reader.ReadInt64(); return new Ref<T>(id); } }
Everything works great except LINQ doesn't support join on the Ref<> properties.
This code can't be compiled because of type mismatch. equals operator strictly requires the same arguments type on both sides of expression. Implementation of IEquatable<long> and implicit conversion operators doesn't help.
from r in DB.Query<SampleWithReference>() join s in DB.Query<Sample>() on r.Parent equals s.Id select s;
The following expression fails because it searches nonexistent path Parent.Id. Meanwhile the db document looks like this: {"Id": 5635634, "Parent": 32412132}.
from r in DB.Query<SampleWithReference>() join s in DB.Query<Sample>() on r.Parent.Id equals s.Id select s;
What I've tried:
- IBsonDocumentSerializer implementation can't help.
- LINQ extension methods are useless because all translator logic is hidden with internal modifier inside driver assembly.
I'm looking for a way to make joins work respecting the provided serializer. It's vitally important for my project. I couldn't find a suitable way to hook LINQ logic.
Any advice will be much appreciated.