如何从 Mongodb 中读取在 c# 中具有重复元素名称的数据
How to read data from Mongodb which have duplicate element name in c#
我在我的 C# MVC 应用程序中使用 MongoDB.Drivers
与 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.
MongoDB资料图片
在上图中,您可以看到我有多个名为 DuplicateCol
的列,它们具有不同的值。
当我尝试使用 MongoDB.Driver
读取 c#
中的这些数据时,出现以下错误:InvalidOperationException: Duplicate element name 'DuplicateCol'.
虽然插入重复的元素名称,但我使用了 BsonDocument
对象的 AllowDuplicateNames=true
,如下所示。 (插入重复的元素名称没有错误。)
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);
注意:此架构是必须的。我改不了。
请提供解决此问题的建议。
任何帮助将不胜感激..
谢谢。
您收到的错误是设计使然
InvalidOperationException: Duplicate element name 'DuplicateCol'
正如 CodeFuller 所说,MongoDB 文档键应该是唯一的。如果您需要一个包含重复字段名称的文档并且您不能更改此模式,MongoDB 可能不是适合您的数据库解决方案……老实说,我不知道哪个会。尽管似乎可以使用以下方法保存重复键:
AllowDuplicateNames=true
我想您会遇到查询和索引等方面的挑战。
有人认为这种模式是一个非常奇怪的要求。更合适的架构可能是:
{
"_id" : ObjectId("xxx"),
"propTest" : 0,
...
"duplicateCol": [ "Value_Two", "Value_One" ]
}
这里有一个 属性 (duplicateCol),它是一个接受多个字符串的数组。
如果没有其他帮助,您查看了其他答案和评论,并且仍然认为您绝对必须保留问题中描述的设计,您可以使用以下 hack。像这样创建 class:
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);
}
}
这是 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());
通过在启动时的某处执行此操作,您将能够读回具有重复属性的文档。
完整的测试代码:
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);
}
}
}
}
}
我在我的 C# MVC 应用程序中使用 MongoDB.Drivers
与 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.
MongoDB资料图片
在上图中,您可以看到我有多个名为 DuplicateCol
的列,它们具有不同的值。
当我尝试使用 MongoDB.Driver
读取 c#
中的这些数据时,出现以下错误:InvalidOperationException: Duplicate element name 'DuplicateCol'.
虽然插入重复的元素名称,但我使用了 BsonDocument
对象的 AllowDuplicateNames=true
,如下所示。 (插入重复的元素名称没有错误。)
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);
注意:此架构是必须的。我改不了。
请提供解决此问题的建议。 任何帮助将不胜感激..
谢谢。
您收到的错误是设计使然
InvalidOperationException: Duplicate element name 'DuplicateCol'
正如 CodeFuller 所说,MongoDB 文档键应该是唯一的。如果您需要一个包含重复字段名称的文档并且您不能更改此模式,MongoDB 可能不是适合您的数据库解决方案……老实说,我不知道哪个会。尽管似乎可以使用以下方法保存重复键:
AllowDuplicateNames=true
我想您会遇到查询和索引等方面的挑战。
有人认为这种模式是一个非常奇怪的要求。更合适的架构可能是:
{
"_id" : ObjectId("xxx"),
"propTest" : 0,
...
"duplicateCol": [ "Value_Two", "Value_One" ]
}
这里有一个 属性 (duplicateCol),它是一个接受多个字符串的数组。
如果没有其他帮助,您查看了其他答案和评论,并且仍然认为您绝对必须保留问题中描述的设计,您可以使用以下 hack。像这样创建 class:
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);
}
}
这是 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());
通过在启动时的某处执行此操作,您将能够读回具有重复属性的文档。
完整的测试代码:
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);
}
}
}
}
}