【问题标题】:Mongo db C# update.SetWrapped method not invoking Custom Bson SerializerMongo db C# update.SetWrapped 方法不调用自定义 Bson 序列化器
【发布时间】:2014-09-04 12:02:15
【问题描述】:

我已经实现了一个自定义 Bson 序列化器,这个自定义 BsonSerializer 似乎在保存和获取 mongo 文档时工作正常。但是在尝试进行更新时,它似乎没有调用序列化程序。

仅供参考, 我添加了 DecimalSerializer ,它将十进制序列化为 Int32 值,并在反序列化时转换回 Decimal 值。因此,在更新十进制值时,它不会调用任何序列化程序。

更新语句:Update.SetWrapped("Tiers.$.Price", tier.Price),这是在 mongo db 中保存为字符串类型。

【问题讨论】:

    标签: c# mongodb serialization mongodb-.net-driver


    【解决方案1】:

    似乎某些版本的驱动程序不会在更新时运行 bson 序列化程序

    https://github.com/mongodb/mongo-csharp-driver/blob/e455c963cb385b94fdcd02d1e53b536b47663239/src/MongoDB.Driver/MongoCollection.cs

        public virtual WriteConcernResult Update(IMongoQuery query, IMongoUpdate update, MongoUpdateOptions options)
        {
            var updateBuilder = update as UpdateBuilder;
            if (updateBuilder != null)
            {
                if (updateBuilder.Document.ElementCount == 0)
                {
                    throw new ArgumentException("Update called with an empty UpdateBuilder that has no update operations.");
                }
            }
    
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
    
            var queryDocument = query == null ? new BsonDocument() : query.ToBsonDocument();
            var updateDocument = update.ToBsonDocument();
            var messageEncoderSettings = GetMessageEncoderSettings();
            var isMulti = options.Flags.HasFlag(UpdateFlags.Multi);
            var isUpsert = options.Flags.HasFlag(UpdateFlags.Upsert);
            var writeConcern = options.WriteConcern ?? _settings.WriteConcern ?? WriteConcern.Acknowledged;
    
            var operation = new UpdateOpcodeOperation(_collectionNamespace, queryDocument, updateDocument, messageEncoderSettings)
            {
                IsMulti = isMulti,
                IsUpsert = isUpsert,
                WriteConcern = writeConcern
            };
    
            using (var binding = _server.GetWriteBinding())
            {
                return operation.Execute(binding, Timeout.InfiniteTimeSpan, CancellationToken.None);
            }
        }
    

    但保存时确实会发生

        public virtual WriteConcernResult Save(Type nominalType, object document, MongoInsertOptions options)
        {
            if (nominalType == null)
            {
                throw new ArgumentNullException("nominalType");
            }
            if (document == null)
            {
                throw new ArgumentNullException("document");
            }
    
            var serializer = BsonSerializer.LookupSerializer(document.GetType());
    

    对我来说,这实际上源于这样一个事实,即序列化程序可能必须拥有整个对象,而在执行更新时,整个对象永远不会到达客户端。这很可能是意料之中的。您的选择:

    1. 在 setWrapped 之前手动序列化 tier.Price
    2. 检查其他版本的驱动程序是否有效(可能不值得)
    3. 向 MongoDB 问题报告错误(Github 页面上的信息)
    4. 避免对十进制类型使用自定义序列化程序(BSON 本身具有双精度数据类型)

    【讨论】:

      猜你喜欢
      • 2019-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多