I am getting the below error while trying to run equal filter against null for a complex type object in MongoDB.Driver 2.0:
InvalidOperationException: Unable to determine the serialization information for e => e.Deletion. at MongoDB.Driver.ExpressionFieldDefinition
2.Render(IBsonSerializer
1 docume ntSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.SimpleFilterDefinition2.Render(IBsonSerializer
1 documentS erializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.AndFilterDefinition1.Render(IBsonSerializer
1 documentSeri alizer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.MongoCollectionImpl1.FindOneAndUpdateAsync[TProjection](Fi lterDefinition
1 filter, UpdateDefinition1 update, FindOneAndUpdateOptions
2 op tions, CancellationToken cancellationToken)
This is the filter:
Builders<TEntity>.Filter.Eq(e => e.Deletion, null)
In order to reproduce, run the following code with MongoDB.Driver 2.0.0 version:
public sealed class OccuranceWithReason
{
public OccuranceWithReason() : this(null)
{
}
public OccuranceWithReason(string reason)
{
Reason = reason;
OccuredOn = DateTime.UtcNow;
}
public string Reason { get; private set; }
public DateTime OccuredOn { get; private set; }
}
public interface IDeletable
{
OccuranceWithReason Deletion { get; }
}
public abstract class BaseEntity : IDeletable
{
protected BaseEntity()
{
Id = ObjectId.GenerateNewId().ToString();
}
public string Id { get; private set; }
public int PeekedCount { get; set; }
public OccuranceWithReason Deletion { get; private set; }
}
public class FooEntity : BaseEntity
{
}
class Program
{
static void Main(string[] args)
{
MongoConfig.Configure();
var client = new MongoClient();
var db = client.GetDatabase("foo");
var fooCol = db.GetCollection<FooEntity>("foos");
var foo = PeekForInsertSync(fooCol);
}
public static TEntity PeekForInsertSync<TEntity>(IMongoCollection<TEntity> collection)
where TEntity : BaseEntity
{
var query = Builders<TEntity>.Filter.And(
Builders<TEntity>.Filter.Eq(e => e.Deletion, null),
Builders<TEntity>.Filter.Lte(e => e.PeekedCount, 10)
);
return collection.Find(query).FirstOrDefaultAsync().Result;
}
}
internal static class MongoConfig
{
public static void Configure()
{
RegisterConventions();
RegisterGlobalSerializationRules();
ConfigureEntities();
ConfigureValueObjects();
}
private static void RegisterConventions()
{
var pack = new ConventionPack { new CamelCaseElementNameConvention(), new IgnoreIfNullConvention(false) };
ConventionRegistry.Register("all", pack, t => true);
}
private static void RegisterGlobalSerializationRules()
{
BsonSerializer.UseNullIdChecker = true;
}
private static void ConfigureEntities()
{
BsonClassMap.RegisterClassMap<BaseEntity>(cm =>
{
cm.MapMember(c => c.Id).SetSerializer(new StringSerializer(BsonType.ObjectId));
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
}
private static void ConfigureValueObjects()
{
BsonClassMap.RegisterClassMap<OccuranceWithReason>(cm =>
{
cm.AutoMap();
cm.MapCreator(occurance => new OccuranceWithReason(occurance.Reason));
});
}
}
Any idea?
The problem is about the BaseEntity object serialization registration. Deletion
property was not mapped. Auto mapping all fields solved the problem:
BsonClassMap.RegisterClassMap<BaseEntity>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Id).SetSerializer(new StringSerializer(BsonType.ObjectId));
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});