有谁知道更新和插入的序列化有什么区别,以及如何使它相等?我遇到的问题就像休耕一样:
假设我们有以下类(忽略它没有MongoId,因为它不相关)
class Custom
{
public string ID { get; set; }
public Dictionary<string, string> Dict { get; set; }
}
当我使用Insert命令时,Json看起来像这样
{
"ID" : "id",
"Dict" :
{
"Key": "Val"
}
}
这是预期的,但在使用Update命令后,Json更改为此
{
"ID" : "id",
"Dict" :
{
"_t" : "System.Collections.Generic.Dictionary`2[System.String,System.String]",
"_v" :
{
"Key": "Val"
}
}
}
这个问题是BsonSerializer在遇到_t / _v语法时会抛出错误。那么,我如何使Update序列化与Insert?
相同注意:
驱动程序版本为2.4.4
IMongoCollection的TDocument始终是BsonDocument
字典只是一个例子,任何具有复杂值的数据类型都会发生这种情况,包括数组
修改
这是代码的简单版本。
static void Main(string[] args)
{
MongoDB.Driver.MongoClient client = new MongoDB.Driver.MongoClient("mongodb://localhost");
MongoDB.Driver.IMongoDatabase db = client.GetDatabase("TestBase");
MongoDB.Driver.IMongoCollection<MongoDB.Bson.BsonDocument> coll = db.GetCollection<MongoDB.Bson.BsonDocument>("TestColl");
Dictionary<string, string> tmpDict = new Dictionary<string, string>();
object tmpDict_o = null;
tmpDict.Add("Key", "Val");
tmpDict_o = tmpDict;
coll.DeleteMany(MongoDB.Driver.Builders<MongoDB.Bson.BsonDocument>.Filter.Empty);
coll.InsertOne(MongoDB.Bson.BsonDocumentWrapper.Create(new Custom() { ID = "id", Dict = tmpDict }));
Console.ReadLine();
coll.UpdateMany(MongoDB.Driver.Builders<MongoDB.Bson.BsonDocument>.Filter.Empty, MongoDB.Driver.Builders<MongoDB.Bson.BsonDocument>.Update.Set("Dict", tmpDict_o));
}
如果在UpdateMany中将tmpDict_o更改为tmpDict,它将按预期工作,但由于我不知道变量将具有哪种类型的值,因此必须将其存储在对象中。 (原始函数将采用任何类型并使用反射提取属性值)
编辑2
通过MongoDB.Driver进行调试我发现mongo遏制的类型是通过查看IMongoCollection的TDocument来键入字段,并且通过使用BsonDocument它将始终采用默认的序列化器(对于System.Object)。所以我的下一个解决方案是打开两个系列;一个用于插入的BsonDocument,另一个用于更新的类型(在此示例中为Custom)。在这种情况下,字典的更新进展顺利,但阵列更糟糕。字符串数组被序列化为字符串,其值为“String [] Array”,复杂类型的数组仍然具有_t / _v语法。
答案 0 :(得分:0)
回答我自己的问题。我在编辑2 中写的部分是正确的,如果TDocument是BsonDocument,文档序列化器将被设置为BsonDocumentSerializer,但是字段序列化器将在UpdateDefinitionBuilder的Set方法中解析。因为变量被声明为
object tmpDict_o = null;
TField永远是对象。要修复此行为,您可以将变量声明为
dynamic tmpDict_o = null;
所以TField将被设置为正确的类型。
注意:
虽然此解决方案有效,但您必须始终将您的类声明为public,否则由于某种原因它将回退到_t / _v语法。