使用C#动态类型进行MongoDB反序列化

时间:2015-04-15 21:54:45

标签: c# mongodb serialization dynamic

我正在使用带有1.10.0驱动程序的MongoDB。我有一个拥有动态成员的实体。该实体包含在父本的一个集合中,该集合最终被序列化。

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

此对象的序列化工作正常,我可以看到有一个额外的属性_tMySubEntity实例序列化,值为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()并从那里过滤。

编辑 - 似乎在Mongo连接的初始化之间发生从“工作”到“不使用上述错误”的更改。我在ASP.NET Web Api中运行。所以初始提交是正常的,随后刷新回数据库工作。直到我重新调试Web应用程序,连接才会失败。

1 个答案:

答案 0 :(得分:1)

您必须指定如何映射文档中定义的类型。

这里有一些样本。在我的项目中任何序列化的类作为接口IDataObject(根对象)或IDatamapped。在应用程序启动时,我确保我的所有类都已注册。

还有更多要说的,你应该检查mongo文档:=)

喜欢:

  1. [BsonDiscriminator(RootClass = true)]
  2. [BsonId(IdGenerator = typeof(ObjectIdGenerator))]
  3. [BsonExtraElements]
  4. 以及如何创建自定义地图。

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