我正在尝试将
[BsonRepresentation(BsonType.ObjectId)]
应用于所有表示为字符串的 id,而无需使用该属性来装饰我的所有 id。
我尝试添加
StringObjectIdIdGeneratorConvention
但这似乎无法对其进行排序。
有什么想法吗?
是的,我也注意到了。由于某种原因,当前的
StringObjectIdIdGeneratorConvention
实施似乎不起作用。这是一个有效的方法:
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
}
public class StringObjectIdIdGeneratorConventionThatWorks : ConventionBase, IPostProcessingConvention
{
/// <summary>
/// Applies a post processing modification to the class map.
/// </summary>
/// <param name="classMap">The class map.</param>
public void PostProcess(BsonClassMap classMap)
{
var idMemberMap = classMap.IdMemberMap;
if (idMemberMap == null || idMemberMap.IdGenerator != null)
return;
if (idMemberMap.MemberType == typeof(string))
{
idMemberMap.SetIdGenerator(StringObjectIdGenerator.Instance).SetSerializer(new StringSerializer(BsonType.ObjectId));
}
}
}
public class Program
{
static void Main(string[] args)
{
ConventionPack cp = new ConventionPack();
cp.Add(new StringObjectIdIdGeneratorConventionThatWorks());
ConventionRegistry.Register("TreatAllStringIdsProperly", cp, _ => true);
var collection = new MongoClient().GetDatabase("test").GetCollection<Person>("persons");
Person person = new Person();
person.Name = "Name";
collection.InsertOne(person);
Console.ReadLine();
}
}
您可以通过编程方式注册您打算用来表示 mongo 文档的 C# 类。注册时您可以覆盖默认行为(例如将 id 映射到字符串):
public static void RegisterClassMap<T>() where T : IHasIdField
{
if (!BsonClassMap.IsClassMapRegistered(typeof(T)))
{
//Map the ID field to string. All other fields are automapped
BsonClassMap.RegisterClassMap<T>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetIdGenerator(StringObjectIdGenerator.Instance);
});
}
}
然后为您要注册的每个 C# 类调用此函数:
RegisterClassMap<MongoDocType1>();
RegisterClassMap<MongoDocType2>();
您要注册的每个类都必须实现
IHasIdField
接口:
public class MongoDocType1 : IHasIdField
{
public string Id { get; set; }
// ...rest of fields
}
需要注意的是,这不是一个全局解决方案,您仍然需要手动迭代您的类。
从驱动程序版本
2.19.1
开始,StringIdStoredAsObjectIdConvention
开箱即用:
var pack = new ConventionPack
{
new StringIdStoredAsObjectIdConvention()
};
ConventionRegistry.Register("YourConventionName", pack, t => true);
您的文档必须具有名称为
Id
、id
或 _id
的字符串属性。