"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(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)
这是过滤器:
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));
});
在 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)
这是过滤器:
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));
});