|
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.
|