簡體   English   中英

FormatException:無法從 BsonType 'ObjectId' 反序列化 'Guid'

[英]FormatException: Cannot deserialize a 'Guid' from BsonType 'ObjectId'

最近幾天我一直在發瘋。

我正在嘗試使用最新版本的驅動程序在我的 MongoDb 中使用字符串 Guids 作為 _id。 我偶然發現了這個教程,它讓我明白了一些......

使用 C# 在 MongoDB 中將 GUID 存儲為字符串

但我收到此錯誤: FormatException:無法從 BsonType 'ObjectId' 反序列化 'Guid'。

   MongoDB.Bson.Serialization.Serializers.GuidSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
MongoDB.Bson.Serialization.Serializers.SerializerBase<TValue>.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize(IBsonSerializer serializer, BsonDeserializationContext context)
MongoDB.Bson.Serialization.BsonClassMapSerializer<TClass>.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)

堆棧跟蹤:

 at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeClass(BsonDeserializationContext context)
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
   at MongoDB.Driver.Core.Operations.CursorBatchDeserializationHelper.DeserializeBatch[TDocument](RawBsonArray batch, IBsonSerializer`1 documentSerializer, MessageEncoderSettings messageEncoderSettings)
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateFirstCursorBatch(BsonDocument cursorDocument)
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.CreateCursor(IChannelSourceHandle channelSource, BsonDocument commandResult)
   at MongoDB.Driver.Core.Operations.FindCommandOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.FindOperation`1.Execute(IReadBinding binding, CancellationToken cancellationToken)
   at MongoDB.Driver.OperationExecutor.ExecuteReadOperation[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass45_0`1.<FindSync>b__0(IClientSessionHandle session)
   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
   at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.AsyncCursorSourceEnumerableAdapter`1.GetEnumerator()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()

我在網上搜索了答案。

我不想使用 POCO 的裝飾,也不想返回BsonDocuments 已經走這條路了:

BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
            BsonSerializer.RegisterSerializer<Guid>(new GuidSerializer(GuidRepresentation.Standard));

並沒有工作。 還做了大會的事...

public class GuidAsStringRepresentationConvention : ConventionBase, IMemberMapConvention
    {
        public void Apply(BsonMemberMap memberMap)
        {
            if (memberMap.MemberType == typeof(Guid))
                memberMap.SetSerializer(new GuidSerializer(BsonType.String));
            
            else if (memberMap.MemberType == typeof(Guid?))
                memberMap.SetSerializer(new NullableSerializer<Guid>(new GuidSerializer(BsonType.String)));
        }
    }

也沒用。。。

這是我的代碼:

public class TestClass
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public bool IsActive { get; set; }
    }

這在 Db 連接之前被調用:

if (!BsonClassMap.IsClassMapRegistered(typeof(TestClass)))
        {
            BsonClassMap.RegisterClassMap<TestClass>(cm =>
            {
                cm.MapIdMember(m => m.Id).SetOrder(0);
                cm.MapMember(m => m.Name).SetOrder(1);
                cm.MapMember(m => m.IsActive).SetOrder(2);
            });
        }

var conn = configuration.GetConnectionString("MongoDb");
            var name = MongoUrl.Create(conn).DatabaseName;
            var client = new MongoClient(conn);
            _db = client.GetDatabase(name); 

之后,我嘗試獲取記錄,在構造函數中初始化集合之后......

public async Task<IEnumerable<TestClass>> ReadAllAsync(CancellationToken cancellationToken = default)
        {
            var filter = Builders<TestClass>.Filter.Empty;
            var items = await _collection.Find<TestClass>(filter).ToListAsync(cancellationToken: cancellationToken);

            return items;
        }

當然,我在 Startup.cs 中的“ConfigureServices”上初始化序列化程序

BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));

最后,帶有字符串 GUID(或 UUID)的 BSON 文檔:

{ 
    "_id" : "c2ea54fc-3942-4ad5-8315-9e96cc5de034", 
    "name" : "I'm Going Crazy", 
    "isActive" : true
}

如果有人能解釋一下,我將不勝感激。 謝謝!!!!

[更新]

我這樣做了:

var col = _db.GetCollection<BsonDocument>("TestCollection");
var list = col.Find(FilterDefinition<BsonDocument>.Empty).ToList();

...我可以看到字符串 GUID,一切都完美加載。 它只是沒有正確解析。 我不知道為什么。 我拒絕手動解析這個文件!!!! 這才是司機應該做的!

[更新 2]

決定用以下方式裝飾該物業:

[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public Guid Id { get; set; }

也沒用。。。

如果您想繼續在本機使用 Guid(而不是將它們視為字符串),請更改您正在注冊的序列化程序。

消除:

BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));

並將其替換為:

BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;

是的,第二行(在撰寫本文時)是一種過時的方法,但目前它是唯一的方法。 是 c# 驅動程序的開放錯誤

這里似乎確實存在需要解決的問題。

從長遠來看,我們鼓勵大家使用新的 V3 GuidRepresentationMode,事實上,當使用 V3 模式時,這個 bug 似乎不會發生。 我添加了以下代碼行作為 main 的第一行:

 BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;

我們仍然需要弄清楚如何讓您的代碼在 V2 模式下工作,但如果您願意使用 V3 模式,您可以立即找到解決方法。

顯然,我使用的 GUID 不是有效的 GUID。 我使用在線生成器生成它們。

我在另一個網站上生成了新的,瞧。 一切都奏效了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM