如何使用 C# 为 Mongodb 中的子文档创建 ID
How to create ids for subdocuments in Mongodb with c#
我正在尝试为 mongodb 中的子文档自动创建 ID。
我有以下课程:
public class Test
{
public string Id {get;set;}
public List<SubTest> SubTestList{get;set;}
public Test()
{
SubTestList = new List<SubTest>();
}
}
public class SubTest
{
public string Id {get;set;}
public string Name {get;set;}
}
另一个将用于存储在 MongoDB 中的 Dll 是这样的(出于解耦的原因,它有一个自己的 dll):
public class TestMongo : Test
{
static TestMongo()
{
//using this instead of attributes above every needed property. will avoid dependencies to mongodb.
BsonClassMap.RegisterClassMap<Test>(cm =>
{
cm.AutoMap();
//register property "Id" to be the mongodb.
cm.SetIdMember(cm.GetMemberMap(c => c.Id).SetRepresentation(BsonType.ObjectId));
//Will generate an Id and set the Id-Property which is a string in this class.
cm.IdMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance);
});
}
}
我正在以编程方式将属性添加到属性中,以确保在使用测试类时不依赖于 Mongo。
现在我需要为每个创建的子测试元素自动创建一个 Id。
我试图在 TestMongo-Constructor 中添加另一个地图,但没有成功:
...
BsonClassMap.RegisterClassMap<SubTest>(cm =>
{
cm.AutoMap();
//register property "Id" to be the mongodb.
cm.SetIdMember(cm.GetMemberMap(c => c.Id).SetRepresentation(BsonType.ObjectId));
//Will generate an Id and set the Id-Property which is a string in this class.
cm.IdMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance);
});
当然,我可以在将其写入 mongo 之前遍历所有子测试元素,但我更愿意让 c#-driver 为我做这件事。
我有办法做到这一点吗?
这种方式为 mongo 使用自定义对象序列化器:
1- 编写序列化程序:
public class TestSerialzer : IBsonSerializer
{
public object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
{
return BsonSerializer.Deserialize<Test>(bsonReader);
}
public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
throw new NotImplementedException();
}
public IBsonSerializationOptions GetDefaultSerializationOptions()
{
throw new NotImplementedException();
}
public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var test = (Test)value;
bsonWriter.WriteStartDocument();
if (string.IsNullOrEmpty(test.Id)) test.Id = ObjectId.GenerateNewId().ToString();
bsonWriter.WriteString("_id", test.Id);
foreach (var nestedObj in test.SubTestList)
{
if (string.IsNullOrEmpty(nestedObj.Id)) nestedObj.Id = ObjectId.GenerateNewId().ToString();
}
bsonWriter.WriteStartArray("SubTestList");
BsonSerializer.Serialize(bsonWriter, test.SubTestList);
bsonWriter.WriteEndArray();
bsonWriter.WriteEndDocument();
}
}
在您的应用程序启动时注册序列化程序:
BsonSerializer.RegisterSerializer(typeof(Test), new TestSerialzer());
和下面的测试对象:
var test = new Test
{
SubTestList = new List<SubTest>
{
new SubTest
{
Name = "Name1",
},
new SubTest
{
Name = "Name2",
},
},
};
collection.Insert(test);
你将拥有:
{
"_id" : "54ad5b25e8b07a214c390ccf",
"SubTestList" : [
[
{
"_id" : "54ad5b25e8b07a214c390cd0",
"Name" : "Name1"
},
{
"_id" : "54ad5b25e8b07a214c390cd1",
"Name" : "Name2"
}
]
]
}
一个简单的解决方案:
using MongoDB.Bson;
myNewSubdocument.Id = ObjectId.GenerateNewId().ToString();
我正在尝试为 mongodb 中的子文档自动创建 ID。
我有以下课程:
public class Test
{
public string Id {get;set;}
public List<SubTest> SubTestList{get;set;}
public Test()
{
SubTestList = new List<SubTest>();
}
}
public class SubTest
{
public string Id {get;set;}
public string Name {get;set;}
}
另一个将用于存储在 MongoDB 中的 Dll 是这样的(出于解耦的原因,它有一个自己的 dll):
public class TestMongo : Test
{
static TestMongo()
{
//using this instead of attributes above every needed property. will avoid dependencies to mongodb.
BsonClassMap.RegisterClassMap<Test>(cm =>
{
cm.AutoMap();
//register property "Id" to be the mongodb.
cm.SetIdMember(cm.GetMemberMap(c => c.Id).SetRepresentation(BsonType.ObjectId));
//Will generate an Id and set the Id-Property which is a string in this class.
cm.IdMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance);
});
}
}
我正在以编程方式将属性添加到属性中,以确保在使用测试类时不依赖于 Mongo。
现在我需要为每个创建的子测试元素自动创建一个 Id。 我试图在 TestMongo-Constructor 中添加另一个地图,但没有成功:
...
BsonClassMap.RegisterClassMap<SubTest>(cm =>
{
cm.AutoMap();
//register property "Id" to be the mongodb.
cm.SetIdMember(cm.GetMemberMap(c => c.Id).SetRepresentation(BsonType.ObjectId));
//Will generate an Id and set the Id-Property which is a string in this class.
cm.IdMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance);
});
当然,我可以在将其写入 mongo 之前遍历所有子测试元素,但我更愿意让 c#-driver 为我做这件事。
我有办法做到这一点吗?
这种方式为 mongo 使用自定义对象序列化器:
1- 编写序列化程序:
public class TestSerialzer : IBsonSerializer
{
public object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
{
return BsonSerializer.Deserialize<Test>(bsonReader);
}
public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
{
throw new NotImplementedException();
}
public IBsonSerializationOptions GetDefaultSerializationOptions()
{
throw new NotImplementedException();
}
public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
{
var test = (Test)value;
bsonWriter.WriteStartDocument();
if (string.IsNullOrEmpty(test.Id)) test.Id = ObjectId.GenerateNewId().ToString();
bsonWriter.WriteString("_id", test.Id);
foreach (var nestedObj in test.SubTestList)
{
if (string.IsNullOrEmpty(nestedObj.Id)) nestedObj.Id = ObjectId.GenerateNewId().ToString();
}
bsonWriter.WriteStartArray("SubTestList");
BsonSerializer.Serialize(bsonWriter, test.SubTestList);
bsonWriter.WriteEndArray();
bsonWriter.WriteEndDocument();
}
}
在您的应用程序启动时注册序列化程序:
BsonSerializer.RegisterSerializer(typeof(Test), new TestSerialzer());
和下面的测试对象:
var test = new Test
{
SubTestList = new List<SubTest>
{
new SubTest
{
Name = "Name1",
},
new SubTest
{
Name = "Name2",
},
},
};
collection.Insert(test);
你将拥有:
{
"_id" : "54ad5b25e8b07a214c390ccf",
"SubTestList" : [
[
{
"_id" : "54ad5b25e8b07a214c390cd0",
"Name" : "Name1"
},
{
"_id" : "54ad5b25e8b07a214c390cd1",
"Name" : "Name2"
}
]
]
}
一个简单的解决方案:
using MongoDB.Bson;
myNewSubdocument.Id = ObjectId.GenerateNewId().ToString();