zor*_*pro 9 c# mongodb mongodb-.net-driver
我已经为我的集合实现了Repository模式和基本实体类.到现在为止所有集合了_id的ObjectId类型.在代码中,我需要将其表示Id为字符串.
这是EntityBase班级的样子
public abstract class EntityBase
{
[BsonRepresentation(BsonType.ObjectId)]
public virtual string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是映射:
BsonClassMap.RegisterClassMap<EntityBase>(cm =>
{
cm.AutoMap();
cm.MapIdProperty(x => x.Id).SetIdGenerator(StringObjectIdGenerator.Instance);
cm.IdMemberMap.SetSerializer(new StringSerializer().WithRepresentation(BsonType.ObjectId));
});
Run Code Online (Sandbox Code Playgroud)
现在我有一个语言集合,其中Id将是简单的字符串en-GB.
{
"_id" : "en-GB",
"Term1" : "Translation 1",
"Term2" : "Translation 2"
}
Run Code Online (Sandbox Code Playgroud)
Languageclass继承了这个EntityBase类
public class Language : EntityBase
{
[BsonExtraElements]
public IDictionary<string, object> Terms { get; set; }
public override string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
问题是我可以以某种方式改变Id仅为Language类而序列化的方式吗?
我不想改变EntityBase类的行为,因为我有很多其他集合继承了EntityBase.
这是我尝试过的例外情况.不确定我尝试过的是否可行.
BsonClassMap.RegisterClassMap<Language>(cm =>
{
cm.AutoMap();
cm.MapExtraElementsMember(c => c.Terms);
cm.MapIdProperty(x => x.Id).SetIdGenerator(StringObjectIdGenerator.Instance);
cm.IdMemberMap.SetSerializer(new StringSerializer().WithRepresentation(BsonType.String));
});
Run Code Online (Sandbox Code Playgroud)
以下是我得到的例外情况:
An exception of type 'System.ArgumentOutOfRangeException' occurred in MongoDB.Bson.dll but was not handled in user code
Additional information: The memberInfo argument must be for class Language, but was for class EntityBase.
at MongoDB.Bson.Serialization.BsonClassMap.EnsureMemberInfoIsForThisClass(MemberInfo memberInfo)
at MongoDB.Bson.Serialization.BsonClassMap.MapMember(MemberInfo memberInfo)
at MongoDB.Bson.Serialization.BsonClassMap`1.MapMember[TMember](Expression`1 memberLambda)
at MongoDB.Bson.Serialization.BsonClassMap`1.MapProperty[TMember](Expression`1 propertyLambda)
at MongoDB.Bson.Serialization.BsonClassMap`1.MapIdProperty[TMember](Expression`1 propertyLambda)
at Test.Utilities.MongoDbClassConfig.<>c.<Configure>b__0_1(BsonClassMap`1 cm) in F:\Development\Test\Utilities\MongoDbClassConfig.cs:line 23
at MongoDB.Bson.Serialization.BsonClassMap`1..ctor(Action`1 classMapInitializer)
at MongoDB.Bson.Serialization.BsonClassMap.RegisterClassMap[TClass](Action`1 classMapInitializer)
at Test.Utilities.MongoDbClassConfig.Configure() in F:\Development\Test\Utilities\MongoDbClassConfig.cs:line 20
at Test.Portal.BackEnd.Startup..ctor(IHostingEnvironment env) in F:\Development\Test\Startup.cs:line 43
Run Code Online (Sandbox Code Playgroud)
我的答案可能迟到了,但我遇到了同样的问题,找到了这个问题,但没有真正的答案如何解决以及为什么会发生。
发生的事情是 Mongo 驱动程序没有明确理解多态性,您必须手动提及每种类型。从同一类继承的所有类型都必须列出并解释为BsonClassMap.
在您的情况下,当您定义 EntityBase 时,您可以列出将被序列化的所有子项,它会使其正常工作。所以类似的东西:
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(Language), typeof(OtherEntity))]
public abstract class EntityBase
{
[BsonId]
public virtual string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
应该管用。就我而言,我想要一个通用的实体保存方法,而我的实体不知道 Mongo 驱动程序,因此我无法使用属性。我在 EntityBase 中有我的 ID,所以这里有一个简单的通用 add 方法(只是相关但有效的部分):
public async Task Add<T>(T item) where T : EntityBase, new()
{
BsonClassMap.RegisterClassMap<EntityBase>(cm =>
{
cm.AutoMap();
cm.MapIdMember(p => p.Id);
cm.SetIsRootClass(true);
});
BsonClassMap.RegisterClassMap<T>();
await Db.GetCollection<T>(typeof(T).Name).InsertOneAsync(item);
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我必须将基类映射到每个条目。然后对象被正确序列化并保存在数据库中。
当您使用[BsonRepresentation(BsonType.ObjectId)]您告诉序列化程序的属性时,即使这是一个字符串 - 您希望它由ObjectId类型表示."en-GB"不是有效的ObjectId,序列化程序抛出异常.
[BsonId]如果要指定名称的属性Id必须是集合中的唯一标识符,请使用-attribute .
ObjectId驱动程序中还有一个-data类型,您可以实现它.
我会在你的EntityBase-class中添加一个泛型类型参数.
public abstract class EntityBase<TId>
{
[BsonId]
public TId Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
您还可以实现EntityBase-class,而不使用泛型类型参数:
public abstract class EntityBase : EntityBase<ObjectId>
{
}
Run Code Online (Sandbox Code Playgroud)
然后为你的Language类
public class Language : EntityBase<string>
{
[BsonExtraElements]
public IDictionary<string, object> Terms { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
驾驶员不应有序列化的一个字符串表示的任何麻烦ObjectId到ObjectId; 但我会先尝试 - 只是为了确保.
| 归档时间: |
|
| 查看次数: |
4195 次 |
| 最近记录: |