MongoDB 使用 C# 动态类型反序列化
MongoDB Deserialization with C# Dynamic Type
我正在使用带有 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; }
}
这个对象的序列化工作正常,我可以看到有一个额外的 属性 _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 - 从 "Works" 到 "Not working with above error" 的变化似乎发生在 Mongo 连接的初始化之间。我在 ASP.NET 网络 Api 中 运行。所以初始提交没问题,后续刷新回数据库工作。直到我重新调试网络应用程序才连接失败。
您必须指定如何映射文档中定义的类型。
这里有一些示例。在我的项目中,任何序列化 class 作为接口 IDataObject(根对象)或 IDatamapped。在应用程序启动时,我确保我所有的 classes 都已注册。
关于它还有更多要说的你应该查看 mongo 文档 :=)
喜欢:
- [BsonDiscriminator(RootClass = true)]
- [BsonId(IdGenerator = typeof(ObjectIdGenerator))]
- [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;
}
}
}
我正在使用带有 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; }
}
这个对象的序列化工作正常,我可以看到有一个额外的 属性 _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 - 从 "Works" 到 "Not working with above error" 的变化似乎发生在 Mongo 连接的初始化之间。我在 ASP.NET 网络 Api 中 运行。所以初始提交没问题,后续刷新回数据库工作。直到我重新调试网络应用程序才连接失败。
您必须指定如何映射文档中定义的类型。
这里有一些示例。在我的项目中,任何序列化 class 作为接口 IDataObject(根对象)或 IDatamapped。在应用程序启动时,我确保我所有的 classes 都已注册。
关于它还有更多要说的你应该查看 mongo 文档 :=)
喜欢:
- [BsonDiscriminator(RootClass = true)]
- [BsonId(IdGenerator = typeof(ObjectIdGenerator))]
- [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;
}
}
}