MongoDB 在按 Id 过滤期间,驱动程序无法将自定义序列化程序转换为 IBsonSerializer
MongoDB driver unable cast custom serializer to IBsonSerializer during filter by Id
我正在使用 C# 开发一个应用程序。我在通过 Id 从 MongoDB.
获取文档时遇到了一些问题
我的Id不是ObjectId而是Guid
模型很简单 POCO。
public class Folder
{
public Guid Id { get; set; }
public int OrgId { get; set; }
// rest props is not important
}
在创建存储库实例(静态构造函数)期间,我注册了 class 映射:
static MongoDBFolderRepository()
{
Init();
}
private static void Init()
{
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
BsonClassMap.RegisterClassMap<Folder>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetSerializer(new MyGuidSerializer());
cm.SetIgnoreExtraElements(true);
});
}
而且我还指定了我自己的序列化程序:
[BsonSerializer(typeof(MyGuidSerializer))]
public class MyGuidSerializer : IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
public Type ValueType
{
get { return typeof(Guid); }
}
}
现在这是抛出异常的方法:
public async Task<Folder> GetFolderAsync(Guid folderId)
{
var database = MongoDBHelper.GetDatabase();
var collection = database.GetCollection<Folder>(CollectionName);
return await collection.Find(Builders<Folder>.Filter.Eq(x => x.Id, folderId)).SingleAsync();
}
例外情况是:
Unable to cast object of type 'MyApp.Repositories.Reporting.Concrete.MyGuidSerializer' to type 'MongoDB.Bson.Serialization.IBsonSerializer`1[System.Guid]'.
System.InvalidCastException
通常序列化有效。如果我将方法更改为此版本:
public async Task<Folder> GetFolderAsync(Guid folderId)
{
var database = MongoDBHelper.GetDatabase();
var collection = database.GetCollection<Folder>(CollectionName);
return await collection.Find(Builders<Folder>.Filter.Eq("_id", folderId.ToString())).SingleAsync();
}
我会进入 return 正确填充的 Folder
模型。
我做错了什么?
你为什么要首先尝试序列化到 string
?
您应该可以直接 serializing/deserializing 到 Guid 来解决您的问题:
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Guid value)
{
var data = new BsonBinaryData(value);
context.Writer.WriteBinaryData(data);
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return BsonSerializer.Deserialize<Guid>(context.Reader);
}
我不知道为什么,但在将界面更改为 IBsonSerializer<Guid>
后一切正常。
[BsonSerializer(typeof(MyGuidSerializer))]
public class MyGuidSerializer : IBsonSerializer<Guid>
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Guid value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
Guid IBsonSerializer<Guid>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
public Type ValueType
{
get { return typeof(Guid); }
}
}
一般通用接口继承 IBsonSerializer,所以我不明白为什么如果我将 IBsonSerializer
实现为 MyGuidSerializer 我得到 Unable cast to IBsonSerializer
。
是的,但是将实现的接口从 IBsonSerializer
更改为 IBsonSerializer<Guid>
解决了问题。
Mongodb.CsharpDriver 2.4.4
我正在使用 C# 开发一个应用程序。我在通过 Id 从 MongoDB.
获取文档时遇到了一些问题我的Id不是ObjectId而是Guid
模型很简单 POCO。
public class Folder
{
public Guid Id { get; set; }
public int OrgId { get; set; }
// rest props is not important
}
在创建存储库实例(静态构造函数)期间,我注册了 class 映射:
static MongoDBFolderRepository()
{
Init();
}
private static void Init()
{
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
BsonClassMap.RegisterClassMap<Folder>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetSerializer(new MyGuidSerializer());
cm.SetIgnoreExtraElements(true);
});
}
而且我还指定了我自己的序列化程序:
[BsonSerializer(typeof(MyGuidSerializer))]
public class MyGuidSerializer : IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
public Type ValueType
{
get { return typeof(Guid); }
}
}
现在这是抛出异常的方法:
public async Task<Folder> GetFolderAsync(Guid folderId)
{
var database = MongoDBHelper.GetDatabase();
var collection = database.GetCollection<Folder>(CollectionName);
return await collection.Find(Builders<Folder>.Filter.Eq(x => x.Id, folderId)).SingleAsync();
}
例外情况是:
Unable to cast object of type 'MyApp.Repositories.Reporting.Concrete.MyGuidSerializer' to type 'MongoDB.Bson.Serialization.IBsonSerializer`1[System.Guid]'.
System.InvalidCastException
通常序列化有效。如果我将方法更改为此版本:
public async Task<Folder> GetFolderAsync(Guid folderId)
{
var database = MongoDBHelper.GetDatabase();
var collection = database.GetCollection<Folder>(CollectionName);
return await collection.Find(Builders<Folder>.Filter.Eq("_id", folderId.ToString())).SingleAsync();
}
我会进入 return 正确填充的 Folder
模型。
我做错了什么?
你为什么要首先尝试序列化到 string
?
您应该可以直接 serializing/deserializing 到 Guid 来解决您的问题:
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Guid value)
{
var data = new BsonBinaryData(value);
context.Writer.WriteBinaryData(data);
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return BsonSerializer.Deserialize<Guid>(context.Reader);
}
我不知道为什么,但在将界面更改为 IBsonSerializer<Guid>
后一切正常。
[BsonSerializer(typeof(MyGuidSerializer))]
public class MyGuidSerializer : IBsonSerializer<Guid>
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Guid value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
Guid IBsonSerializer<Guid>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
return Guid.Parse(BsonSerializer.Deserialize<string>(context.Reader));
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
BsonSerializer.Serialize(context.Writer, value.ToString());
}
public Type ValueType
{
get { return typeof(Guid); }
}
}
一般通用接口继承 IBsonSerializer,所以我不明白为什么如果我将 IBsonSerializer
实现为 MyGuidSerializer 我得到 Unable cast to IBsonSerializer
。
是的,但是将实现的接口从 IBsonSerializer
更改为 IBsonSerializer<Guid>
解决了问题。
Mongodb.CsharpDriver 2.4.4