代码之家  ›  专栏  ›  技术社区  ›  sebcza

MongoDB驱动程序无法在按Id筛选期间将自定义序列化程序强制转换为IBMOSonSerializer

  •  1
  • sebcza  · 技术社区  · 7 年前

    我正在用C语言编写一个应用程序。我在从MongoDB获取Id文档时遇到一些问题。

    我的Id不是ObjectId,而是Guid。

    模型是简单的POCO。

    public class Folder
    {
            public Guid Id { get; set; }
            public int OrgId { get; set; }
            // rest props is not important
    }
    

    在创建存储库实例(静态构造函数)的过程中,我注册了类映射:

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

    例外情况是:

    无法强制转换类型为“MyApp”的对象。存储库。报告。混凝土MyGuidSerializer“输入”MongoDB。Bson公司。序列化。IBMOSonSerializer“1[系统Guid]”。

    系统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();
        }
    

    我会得到正确填写的回报 Folder 模型

    我做错了什么?

    2 回复  |  直到 7 年前
        1
  •  4
  •   sebcza    7 年前

    我不知道为什么,但更改界面后 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); }
        }
    }
    

    一般来说,通用接口继承IBMOSonSerializer,所以我不明白为什么我要实现 IBsonSerializer 作为我的GuidSerializer Unable cast to IBsonSerializer .

    是的,好的,但更改实现的接口 IBMsonSerializer IBsonSerializer<Guid> 解决问题。

    Mongodb。CsharpDriver 2.4.4

        2
  •  1
  •   marcofo88    7 年前

    为什么要尝试序列化到 string 首先?

    您应该能够通过直接序列化/反序列化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);
        }