如何从Mongodb中读取c#中具有重复元素名称的数据

pro*_*011 5 c# asp.net-mvc mongodb nosql mongodb.driver

MongoDB.Drivers在我的C#MVC应用程序中使用与Mongodb数据库进行通信.

C#代码

            var client = new MongoClient("mongodb://localhost:27012");
            var db = client.GetDatabase("Test_DB");
            var collection = db.GetCollection<BsonDocument>("TestTable");
            var tData = await collection.FindAsync(new BsonDocument(true)); // I used - new BsonDocument(true)  to specify allow duplicate element name while read data.
Run Code Online (Sandbox Code Playgroud)

MongoDB数据图片 在此输入图像描述

在上面的图像中,您可以看到我有多个DuplicateCol使用不同值调用的列.当我尝试在c#使用中读取这些数据时MongoDB.Driver出现以下错误:InvalidOperationException: Duplicate element name 'DuplicateCol'.

插入重复元素名称时我使用AllowDuplicateNames=trueBsonDocument如下对象.(它插入重复的元素名称而不会出错.)

BsonDocument obj = new BsonDocument();
obj.AllowDuplicateNames = true;
obj.Add("DuplicateCol", "Value_One");
obj.Add("propone", "newVal");
obj.Add("DuplicateCol", "Value_Two");
.... // other properties with value 
await collection.InsertOneAsync(obj);
Run Code Online (Sandbox Code Playgroud)

注意:此架构必须.我无法改变它.

请提供解决此问题的建议.任何帮助将受到高度赞赏..

谢谢.

Evk*_*Evk 8

如果没有其他帮助,你查看了其他答案和评论,仍然认为你绝对必须保持问题中描述的设计,你可以使用以下hack.像这样创建类:

class AlwaysAllowDuplicateNamesBsonDocumentSerializer : BsonDocumentSerializer {
    protected override BsonDocument DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args) {
        if (!context.AllowDuplicateElementNames)
            context = context.With(c => c.AllowDuplicateElementNames = true);
        return base.DeserializeValue(context, args);
    }

    public override BsonDocument Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) {
        if (!context.AllowDuplicateElementNames)
            context = context.With(c => c.AllowDuplicateElementNames = true);
        return base.Deserialize(context, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是自定义序列化程序BsonDocument,AllowDuplicateElementNames在反序列化时始终设置.然后你需要一些反射来覆盖默认的BsonDocument序列化器(因为BsonDocumentSerializer.Instance没有setter):

// get __instance field, which is backing field for Instance property
var instanceField = typeof(BsonDocumentSerializer).GetField("__instance", BindingFlags.Static | BindingFlags.NonPublic);
// overwrite with our custom serializer
instanceField.SetValue(null, new AlwaysAllowDuplicateNamesBsonDocumentSerializer());
Run Code Online (Sandbox Code Playgroud)

通过在启动时的某个地方执行此操作,您将能够使用重复的属性读回您的文档.

完整的测试代码:

static void Main(string[] args) {
    var instanceField = typeof(BsonDocumentSerializer).GetField("__instance", BindingFlags.Static | BindingFlags.NonPublic);
    instanceField.SetValue(null, new AlwaysAllowDuplicateNamesBsonDocumentSerializer());
    TestMongoQuery();
    Console.ReadKey();
}

static async void TestMongoQuery() {
    var client = new MongoClient();
    var db = client.GetDatabase("Test_DB");            
    var collection = db.GetCollection<BsonDocument>("TestTable");
    using (var allDocs = await collection.FindAsync(FilterDefinition<BsonDocument>.Empty)) {
        while (allDocs.MoveNext()) {
            foreach (var doc in allDocs.Current) {
                var duplicateElements = doc.Elements.Where(c => c.Name == "DuplicateCol");
                foreach (var el in duplicateElements) {
                    Console.WriteLine(el.Name + ":" + el.Value);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)