#c# #mongodb #serialization #bsondocument #bsonserializer
#c# #mongodb #сериализация #документ bsondocument #bsonserializer
Вопрос:
У меня возникла проблема с сериализацией документов BsonDocuments с помощью BsonSerializer.
Я использую var bsonDoc = collection.Find(...)
для извлечения одного документа из базы данных MongoDB. Затем я пытаюсь сериализовать его с помощью var strongTypedDocument = BsonSerializer.Deserializelt;MainSDocumentgt;(bsonDoc);
Вот документ BsonDocument
{ "MainSPayload" : { "GDeets" : { "Id" : 0, "GSerial" : "XX123XX123" } } }
Вот классы C#
[JsonObject(MemberSerialization.OptIn)] [BsonIgnoreExtraElements] public class MainSDocument { [JsonProperty(Required = Required.Always)] public MainState MainSPayload { get; set; } } [JsonObject(MemberSerialization.OptIn)] public class MainState { [JsonProperty(Required = Required.Always)] public GDetails GDeets { get; set; } } public class GDetails { public int Id { get; set; } public string GSerial { get; set; } }
Ошибка, которую я получаю, заключается в следующем: FormatException: An error occurred while deserializing the GDetails property of class MainState : Element 'Id' does not match any field or property of class GDetails .'
Почему это происходит? Почему элемент не Id
совпадает с элементом int Id
в GDetails
классе?
Комментарии:
1. пожалуйста, покажите нам класс
GroupInfo
2. @Jazb ой! это была опечатка 🙂 исправил ее.
Ответ №1:
Сериализация для Id
поля имеет специальный рабочий процесс, который эффективно преобразует это значение в то, как его представляет серверная сторона: _id
. Чтобы обойти это, вы можете использовать:
BsonClassMap.RegisterClassMaplt;GDetailsgt;(c =gt; { c.AutoMap(); c.UnmapField(u =gt; u.Id); // remove default _id workflow c.MapField(u =gt; u.Id); // add a simple Id field });
или проще:
BsonClassMap.RegisterClassMaplt;GDetailsgt;(c =gt; { c.AutoMap(); c.SetIdMember(null); });
Обновить: Есть немного более гибкий способ. Вы можете настроить новое соглашение и указать, какие типы вам понадобятся при его использовании:
var customPack = new ConventionPack(); customPack.Add(new NoIdMemberConvention()); ConventionRegistry.Register("NoIdConvention", customPack, t =gt; t == typeof(GDetails));
также вместо вышеперечисленного вы можете просто добавить атрибут BsonNoId в свой класс:
[BsonNoId] public class GDetails { public int Id { get; set; } public string GSerial { get; set; } }
Комментарии:
1. Спасибо. Есть ли более общий способ установить это для всех полей идентификаторов без необходимости вводить эти 5 строк кода для каждого класса?
2. Я так не думаю, и это требуется не для каждого класса, только для случаев, когда
Id
средства не на стороне сервера_id
3. Смотрите вышеприведенное обновление
4. Спасибо.
BsonNoId
Атрибут более элегантен, имо..