2015-04-15 2 views
0

Я использую MongoDB с драйвером 1.10.0. У меня есть объект с динамическим членом. Этот объект содержится внутри коллекции самого родителя, который в конечном итоге сериализуется.MongoDB Deserialization with C# Dynamic Type

public class MyEntity 
{ 
    public List<MySubEntity> Items { get; set; } 
} 

public class MySubEntity 
{ 
    public dynamic Value { get; set; } 

    public MySubEntity() 
    { 
     Value = new ValueString(); 
    } 
} 

public class ValueString 
{ 
    public string Value { get; set; } 
} 

сериализации этого объекта работает отлично, и я могу видеть, что есть дополнительное свойство _t сериализовать с MySubEntity экземпляра со значением ValueString.

В первый раз, когда я пытаюсь извлечь это из Mongo, он десериализуется отлично, и все данные выходят. Однако, и будущие попытки потерпят неудачу.

{"An error occurred while deserializing the Answer property of class MySubEntity: Unknown discriminator value 'ValueString'."}

at MongoDB.Bson.Serialization.BsonClassMapSerializer.DeserializeMemberValue(BsonReader bsonReader, BsonMemberMap memberMap) 
at MongoDB.Bson.Serialization.BsonClassMapSerializer.Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) 
at MongoDB.Bson.Serialization.BsonClassMapSerializer.Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) 
at MongoDB.Driver.Internal.MongoReplyMessage`1.ReadBodyFrom(BsonBuffer buffer) 
at MongoDB.Driver.Internal.MongoReplyMessage`1.ReadFrom(BsonBuffer buffer) 
at MongoDB.Driver.Internal.MongoConnection.ReceiveMessage[TDocument](BsonBinaryReaderSettings readerSettings, IBsonSerializer serializer, IBsonSerializationOptions serializationOptions) 
at MongoDB.Driver.Operations.QueryOperation`1.GetFirstBatch(IConnectionProvider connectionProvider) 
at MongoDB.Driver.Operations.QueryOperation`1.Execute(IConnectionProvider connectionProvider) 
at MongoDB.Driver.MongoCursor`1.GetEnumerator() 
at MongoDB.Driver.Linq.IdentityProjector`1.GetEnumerator() 
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source) 
at MongoDB.Driver.Linq.SelectQuery.<TranslateFirstOrSingle>b__b(IEnumerable source) 
at MongoDB.Driver.Linq.SelectQuery.Execute() 
at MongoDB.Driver.Linq.MongoQueryProvider.Execute(Expression expression) 
at MongoDB.Driver.Linq.MongoQueryProvider.Execute[TResult](Expression expression) 
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) 

Есть ли что-то я мог бы не быть о том, как это сделать? Я не могу добавить никаких атрибутов ни к одному из классов, поэтому любые изменения должны быть сделаны из конфигурации времени выполнения.

Чтобы получить доступ к объекту, я использую MongoCollection<T>.AsQueryable() и фильтрую оттуда.

EDIT - Изменение между «Работами» и «Не работает с ошибкой выше» происходит между инициализацией соединения Mongo. Я запускаю ASP.NET Web Api. Таким образом, первоначальная подача в порядке, а затем обновляется до работы с базой данных. Пока я не повторно отлаживаю веб-приложение, соединение не работает.

ответ

1

Вы должны указать, как сопоставить типы, определенные в ваших документах.

Здесь несколько примеров. В моем проекте любой сериализованный класс как интерфейс IDataObject (корневой объект) или IDatamapped. При запуске приложения я гарантирую, что все мои классы зарегистрированы.

Существует больше, чтобы сказать об этом, вы должны проверить документацию Монго: =)

, как:

  1. [BsonDiscriminator (RootClass = истина)]
  2. [BsonId (IdGenerator = TYPEOF (ObjectIdGenerator))]
  3. [BsonExtraElements]

и как создавать собственные карты.

 public static void DefaultMappers(Assembly asm) 
    { 
      foreach (Type t in asm.GetTypes()) 
      { 
       if (t.GetInterface(typeof (IDataObject).Name) != null) 
       { 
        BsonClassMap.LookupClassMap(t); 
        continue; 
       } 

       if (t.GetInterface(typeof(IDataMapped).Name) != null) 
       { 
        BsonClassMap.LookupClassMap(t); 
        continue; 
       } 
      } 
    } 
+0

Мне было трудно понять, когда и что нужно для сопоставления. В принципе, все основные типы (и их дети), которые настроены для использования в коллекциях в Монго, автоматически отображаются на карту. Время, которое вам нужно явно отображать, - это когда вы используете динамику, свойства, поддерживаемые интерфейсом, базовые типы и т. Д. В принципе отобразите любой тип, который явно не объявлен как тип в коллекции. –

+0

Извините за требование о помощи, но можно ли десериализовать динамику и объект для общего BsonDocument? http://stackoverflow.com/questions/36202460/mongodb-unknown-discriminator-value-deserialize-to-jsondocument – Revious

+0

MongoDB.BsonBsonExtensionMethods Принимает ToJson() или ToBsonDocument, ToBson() для любого объекта –