【问题标题】:C# MongoDB multiple type serializationC# MongoDB 多类型序列化
【发布时间】:2022-01-02 00:21:28
【问题描述】:

我使用 MongoDB C# 驱动程序 (2.13.2),并且我使用集合中的此类输入数据,其中一个 Value 字段可以是 nulltrue、“字符串值” 或一个对象

{
  "ItemId": UUID("13202a78-668d-4b17-9aac-78524d50925e"),
  "FieldValue": {
    "FieldName" : "IsCity",
    "Value": true
  }
},
{
  "ItemId": UUID("26566f9a-712d-44fe-9baa-722aa53e0038"),
  "FieldValue": {
    "FieldName" : "Address",
    "Value": "Address"
},
{
  "ItemId": UUID("6640a83a-a47d-4016-9d50-70c41425e099"),
  "FieldValue": {
    "FieldName" : "Address",
    "Value": {
      "Data1": "String",
      "Data2": [
        UUID("a9bde160-22af-4cf7-a201-57db8b392c4d")
      ]
    }
  }
}

这是我的序列化类:

class MyData {
  public Guid ItemId { get; set; }
  public MyFieldValue FieldValue { get; set; }
}

class MyFieldValue {
  public string FieldName { get; set; }
  public Dictionary<string, object> Value { get; set; }
}

我尝试使用字典或 BSON 文档,但由于 truefalse 值,在序列化过程中出现异常:无法反序列化 'Dictionary' 来自 BsonType 'Boolean'。 如何序列化一个可能非常不同的 Value

或者,在序列化时,将布尔值或字符串转换为 { "value": "true" } 形式的对象。然后所有的值都将是一个字典。但是怎么做呢?

【问题讨论】:

  • 也许您只想要BsonValue 而不是Dictionary&lt;string, object&gt;
  • 如果Value 属性的数据类型在编译时未知,您可以使用objectdynamic(基本上是object 加上一些编译器魔法)。跨度>

标签: c# mongodb serialization mongodb-.net-driver


【解决方案1】:

您正在讨论的主题称为“架构版本控制”。见https://www.mongodb.com/blog/post/building-with-patterns-the-schema-versioning-pattern

对于 C#,MongoDB 驱动程序有一些模式版本控制策略。见https://mongodb.github.io/mongo-csharp-driver/2.13/reference/bson/mapping/schema_changes/

在线文档中未描述的一个主题是使用泛型类型并转换为您的特定类型的能力。这不是首选方法,因为它需要对应用程序进行额外的工作来序列化和转换,但如果您不关心这些性能影响,那么这可能是一个值得考虑的想法。

这是一个使用泛型类型 (BsonDocument) 的示例,以说明对数据没有 C# 类型限制。我在您的原始问题(帖子)中使用了您的确切文件。

Test.cs

using MongoDB.Driver;

public class Test
{
    private MongoDB.Driver.IMongoClient client;
    private MongoDB.Driver.IMongoDatabase database; 
    private MongoDB.Driver.IMongoCollection<MongoDB.Bson.BsonDocument> collection;

    public Test()
    {
        #pragma warning disable 0618
        MongoDB.Bson.BsonDefaults.GuidRepresentationMode = MongoDB.Bson.GuidRepresentationMode.V3;
        MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(new MongoDB.Bson.Serialization.Serializers.GuidSerializer(MongoDB.Bson.GuidRepresentation.Standard));
        
        string uri = "mongodb://testuser:mysecret@localhost:50011,localhost:50012,localhost:50013/csharptest?replicaSet=replSet&authSource=admin&retryWrites=true&readConcernLevel=majority";
    
        this.client = new MongoDB.Driver.MongoClient(uri);
        this.database = client.GetDatabase("csharptesting");
        this.collection = database.GetCollection<MongoDB.Bson.BsonDocument>("somecollection");

        // CLEAR OUT ALL THE PRIOR TEST RECORDS
        this.collection.DeleteMany(new MongoDB.Bson.BsonDocument());
    }

    public void insertRecords() 
    {
        System.Console.WriteLine("Begin insert record 1...");
        MongoDB.Bson.BsonDocument document1 = new MongoDB.Bson.BsonDocument {
             {"ItemId", new MongoDB.Bson.BsonBinaryData(new System.Guid("13202a78-668d-4b17-9aac-78524d50925e"), MongoDB.Bson.GuidRepresentation.Standard)},
             {"FieldValue", 
                new MongoDB.Bson.BsonDocument {
                    {"FieldName", "IsCity"},
                    {"Value", true}
                }
             }
        };
        this.collection.InsertOne(document1);
        System.Console.WriteLine("End insert record 1");

        System.Console.WriteLine("Begin insert record 2...");
        MongoDB.Bson.BsonDocument document2 = new MongoDB.Bson.BsonDocument {
             {"ItemId", new MongoDB.Bson.BsonBinaryData(new System.Guid("26566f9a-712d-44fe-9baa-722aa53e0038"), MongoDB.Bson.GuidRepresentation.Standard)},
             {"FieldValue", 
                new MongoDB.Bson.BsonDocument {
                    {"FieldName", "Address"},
                    {"Value", "Address"}
                }
             }
        };
        this.collection.InsertOne(document2);
        System.Console.WriteLine("End insert record 2");


        System.Console.WriteLine("Begin insert record 3...");
        MongoDB.Bson.BsonDocument document3 = new MongoDB.Bson.BsonDocument {
             {"ItemId", new MongoDB.Bson.BsonBinaryData(new System.Guid("6640a83a-a47d-4016-9d50-70c41425e099"), MongoDB.Bson.GuidRepresentation.Standard)},
             {"FieldValue", 
                new MongoDB.Bson.BsonDocument {
                    {"FieldName", "Address"},
                    {"Value", 
                        new MongoDB.Bson.BsonDocument {
                            { "Data1", "String" },
                            { "Data2", new MongoDB.Bson.BsonBinaryData(new System.Guid("a9bde160-22af-4cf7-a201-57db8b392c4d"), MongoDB.Bson.GuidRepresentation.Standard)}
                        }
                    }
                }
             }
        };
        this.collection.InsertOne(document3);
        System.Console.WriteLine("End insert record 3");
    }

    public void find()
    {
        System.Console.WriteLine("Find data...");

        foreach(MongoDB.Bson.BsonDocument record in this.collection.Find(new MongoDB.Bson.BsonDocument()).ToList())
        {
            System.Console.WriteLine(record);
        }

        System.Console.WriteLine("End find data");
    }
}

Program.cs

namespace Full_Example
{
    class Program
    {
        static void Main(string[] args)
        {
            var test = new Test();
            test.insertRecords();
            test.find();
        }
    }
}

输出

Begin insert record 1...
End insert record 1
Begin insert record 2...
End insert record 2
Begin insert record 3...
End insert record 3
Find data...
{ "_id" : ObjectId("619d15d9bd6b57dece960714"), "ItemId" : UUID("13202a78-668d-4b17-9aac-78524d50925e"), "FieldValue" : { "FieldName" : "IsCity", "Value" : true } }
{ "_id" : ObjectId("619d15d9bd6b57dece960715"), "ItemId" : UUID("26566f9a-712d-44fe-9baa-722aa53e0038"), "FieldValue" : { "FieldName" : "Address", "Value" : "Address" } }
{ "_id" : ObjectId("619d15d9bd6b57dece960716"), "ItemId" : UUID("6640a83a-a47d-4016-9d50-70c41425e099"), "FieldValue" : { "FieldName" : "Address", "Value" : { "Data1" : "String", "Data2" : UUID("a9bde160-22af-4cf7-a201-57db8b392c4d") } } }
End find data

结论

您可以使用通用类型访问查询的文档,例如 BsonDocument() 并逐字段访问。使用这种方法,您可以将此 BsonDocument 转换为您的特定类型,但这需要自定义转换器方法。

【讨论】:

  • 一个很好的答案,也许 BsonDocument 的整个对象很多,而 @Llama 建议的一个字段就可以了。
猜你喜欢
  • 1970-01-01
  • 2013-09-09
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 2018-08-01
相关资源
最近更新 更多