简体   繁体   English

具有C#动态类型的MongoDB反序列化

[英]MongoDB Deserialization with C# Dynamic Type

I am using MongoDB with the 1.10.0 driver. 我将MongoDB与1.10.0驱动程序配合使用。 I have an entity with a dynamic member. 我有一个具有动态成员的实体。 This entity is contained within a collection of itself on a parent, which is ultimately serialized. 该实体包含在父实体自身的集合中,该父实体最终被序列化。

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

The serialization of this object works fine, and I can see there is an additional property _t serialized with the MySubEntity instance with a value of ValueString . 该对象的序列化工作正常,我可以看到还有一个附加属性_tMySubEntity实例序列化了,其值是ValueString

The very first time I attempt to retrieve this from Mongo, it deserializes fine and all data comes out. 我第一次尝试从Mongo检索此数据时,它会反序列化,并且所有数据都会出来。 However, and future attempts fail. 但是,将来的尝试失败。

{"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)

Is there something I might be missing on how to do this? 在执行此操作时我可能会缺少什么? I cannot add any attributes to any of the classes, so any changes would need to be done from a runtime configuration. 我无法向任何类添加任何属性,因此需要从运行时配置中进行任何更改。

To access the entity, I'm using MongoCollection<T>.AsQueryable() and filtering from there. 要访问该实体,我正在使用MongoCollection<T>.AsQueryable()并从那里进行过滤。

EDIT - The change from "Works" to "Not working with above error" seems to occur between initializations of the Mongo connection. 编辑 -在Mongo连接的初始化之间,似乎发生了从“ Works”到“不适用于以上错误”的更改。 I am running in an ASP.NET Web Api. 我正在ASP.NET Web Api中运行。 So the initial submission is OK, and subsequent refreshes back to the database work. 这样,初始提交就可以了,随后刷新回到数据库工作。 It's not until I re-debug the web app does the connection fail. 直到我重新调试Web应用程序后,连接才会失败。

You have to specify how to map the types defined in your documents. 您必须指定如何映射文档中定义的类型。

Here some sample. 这里有一些样品。 In my project any serialized class as an Interface IDataObject (root object) or IDatamapped. 在我的项目中,任何序列化的类均作为接口IDataObject(根对象)或IDatamapped。 At application startup I ensure that all my classes are registered. 在应用程序启动时,我确保所有类都已注册。

There is more to say about it you should check the mongo documentation :=) 还有更多要说的,您应该查看mongo文档:=)

Like : 喜欢 :

  1. [BsonDiscriminator(RootClass = true)] [BsonDiscriminator(RootClass = true)]
  2. [BsonId( IdGenerator = typeof(ObjectIdGenerator))] [BsonId(IdGenerator = typeof(ObjectIdGenerator))]
  3. [BsonExtraElements] [BsonExtraElements]

and how to create custom maps. 以及如何创建自定义地图。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM