"Unable to determine the serialization information for" MongoDB 复杂类型等于 null 过滤器时出错

"Unable to determine the serialization information for" error on MongoDB complex type equal to null filter

在 MongoDB.Driver 2.0:

中尝试针对复杂类型对象对空值进行 运行 相等过滤时出现以下错误:

InvalidOperationException: Unable to determine the serialization information for e => e.Deletion. at MongoDB.Driver.ExpressionFieldDefinition2.Render(IBsonSerializer1 docume ntSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.SimpleFilterDefinition2.Render(IBsonSerializer1 documentS erializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.AndFilterDefinition1.Render(IBsonSerializer1 documentSeri alizer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.MongoCollectionImpl1.FindOneAndUpdateAsync[TProjection](Fi lterDefinition1 filter, UpdateDefinition1 update, FindOneAndUpdateOptions2 op tions, CancellationToken cancellationToken)

这是过滤器:

Builders<TEntity>.Filter.Eq(e => e.Deletion, null)

为了重现,运行以下代码使用MongoDB.Driver2.0.0版本:

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));
        });
    }
}

有什么想法吗?

问题是关于BaseEntity对象序列化注册的。 Deletion 属性 未映射。自动映射所有字段解决了问题:

BsonClassMap.RegisterClassMap<BaseEntity>(cm =>
{
    cm.AutoMap();
    cm.MapMember(c => c.Id).SetSerializer(new StringSerializer(BsonType.ObjectId));
    cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});