![](/img/trans.png)
[英]How to combine/merge multiple document to one c# object using C# mongo Db driver in .net core
[英]Mongo DB Document deserialization to C# object for one property fails
僅當查詢對象時,我才收到屬性引用的以下錯誤
反序列化類User的Referrals屬性時發生錯誤:無法反序列化BsonType
String
的List<Nullable<ObjectId>>
。
C#類
[BsonIgnoreExtraElements]
public class User : MongoEntity
{
[BsonDefaultValue(null)]
public List<ObjectId?> referrals { get; set; }
}
查詢文件
var users = MongoConnectionHandler.GetDB().GetCollection<User>("users");
var myusers = users.AsQueryable<User>();
一旦foreach循環迭代,就會發生此異常
foreach (var item in myusers){}
並非僅某些文檔適用於所有文檔。 有什么辦法可以忽略導致該錯誤的文檔?
幸運的是,錯誤消息很清楚,足以理解問題的根本原因。 您在users
集合中有一些文檔以不同的架構保存, referrals
只是一個字符串,而不是ObjectId
的數組。 現在,當您嘗試對這些對象進行反序列化時,您會遇到公平的錯誤,即String
無法反序列化為List<ObjectId?>
。
如果當前您的數據庫僅包含一些測試數據,則可以清除集合並從頭開始。 只要不再保存具有舊模式的文檔,您就不會再次遇到該錯誤。
如果必須保留現有數據,則應手動刪除具有舊架構的文檔或將其數據遷移到新架構,以便可以成功反序列化這些文檔。
但是,如果無法刪除具有過時架構的數據,則應實現自定義序列化程序,以便可以成功從數據庫讀取數據。 以下是一個示例序列化程序,該序列化程序在反序列化期間將忽略String
值:
public class FixingReferralsSerializer : EnumerableSerializerBase<List<ObjectId?>>
{
public override List<ObjectId?> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.String)
{
context.Reader.ReadString();
return null;
}
return base.Deserialize(context, args);
}
protected override void AddItem(object accumulator, object item)
{
((List<ObjectId?>)accumulator).Add((ObjectId?)item);
}
protected override object CreateAccumulator()
{
return new List<ObjectId?>();
}
protected override IEnumerable EnumerateItemsInSerializationOrder(List<ObjectId?> value)
{
return value;
}
protected override List<ObjectId?> FinalizeResult(object accumulator)
{
return (List<ObjectId?>)accumulator;
}
}
您可以通過BsonSerializer
屬性將此序列化程序設置為referrals
字段:
[BsonIgnoreExtraElements]
public class User : Document
{
[BsonDefaultValue(null)]
[BsonSerializer(typeof(FixingReferralsSerializer))]
public List<ObjectId?> referrals { get; set; }
}
如果可以將referrals
字段的類型從List<ObjectId?>
更改為Array<ObjectId?>
則Serializer類將簡單得多。 在這種情況下,您可以基於ArraySerializer<T>
實現序列化程序的實現:
public class FixingReferralsSerializer : ArraySerializer<ObjectId?>
{
public override ObjectId?[] Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.String)
{
context.Reader.ReadString();
return null;
}
return base.Deserialize(context, args);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.