tengo las siguientes clases:MongoDB deserialización Con Discriminador Edición
[BsonIgnoreExtraElements]
public class WidgetCollection
{
[BsonId]
public int AccountId { get; set; }
public ReadOnlyCollection<Widget> Widgets { get; set; }
}
[BsonIgnoreExtraElements]
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(OtherObject1), ...)]
public class Widget
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public int Position { get; set; }
public WidgetKind Kind { get; set; }
public bool IsActive { get; set; }
}
un ejemplo de un ejemplo de esto en el DB:
{ "_id" : 2993644, "Widgets" : [ { "_t" : "Widget", "_id" : ObjectId("504797b327e10b1e80c838ac"), "Title" : "My Notes", "Position" : 1, "Kind" : 0, "IsActive" : true } ] }
entonces tengo un comando de agregación que filtra los elementos en la matriz "Widgets" para devolver solo los elementos cuyo "IsActive" es verdadero. En este caso, el comando simplemente devuelve el objeto completo.
var command = new CommandDocument
{
{"aggregate", "myCollection" },
{"pipeline", commandArray }
};
var result = database.RunCommandAs<AggregateResult<WidgetCollection>>(command).Result;
return result;
Ésta es la clase AggregateResult:
public class AggregateResult<T> : CommandResult
{
public T Result
{
get
{
var result = Response["result"].AsBsonArray.SingleOrDefault().AsBsonDocument;
return BsonSerializer.Deserialize<T>(result);
}
}
}
Sí, sé que SingleOrDefault() AsBsonDocument podría caso de que un NRE, pero ese no es el problema ahora.. He depurado el código hasta el punto de deserialización y he verificado que la variable "resultado" contiene exactamente el mismo BSON que mostré anteriormente. Recibo este mensaje cuando trato de deserializar el resultado: "Ocurrió un error al deserializar la propiedad Widgets de la clase Community.Widgets.WidgetCollection: el nombre del elemento esperado era '_v', no '_id'".
¿Por qué se espera que el deserializador sea un elemento '_v'?
ACTUALIZACIÓN
He arreglado el problema anterior cambiado el tipo de la propiedad widgets para ICollection
. Ahora recibo este error: Unknown discriminator value 'Widget'.
Para mí, esto no tiene sentido ya que el documento tiene el elemento "_t" : "Widget"
.
También intenté insertar una clase derivada, después de lo cual el valor del elemento "_t" ahora era "[ "Widget", "DerivedClass"]
como esperaba, y me sale el mismo error. De nuevo, esto no ocurre cuando se usa database.FindOneAs<>()
, solo cuando se usa explícitamente BsonSerializer.Deserialize<>()
. He intentado añadir este código justo antes de llamar Deserialize()
:
BsonClassMap.RegisterClassMap<Widget>(cm => { cm.AutoMap(); cm.SetIsRootClass(true); });
BsonClassMap.RegisterClassMap<RssFeedWidget>();
Pero no estoy muy seguro de que en el código de inicialización debe ir, y pensé que no era necesario si yo estaba usando los atributos discriminador en mis clases.
Aquí es mi mando agregación
BsonDocument documentMatch = new BsonDocument{{"$match", new BsonDocument{{"_id", documentId}}}};
BsonDocument unwindArray = new BsonDocument{{"$unwind", "$Widgets"}};
BsonDocument arrayMatch = new BsonDocument{{"$match", new BsonDocument{{"Widgets.IsActive", true}}}});
BsonArray commandArray = new BsonArray();
commandArray.Add(documentMatch);
commandArray.Add(unwindArray),
commandArray.Add(arrayMatch);
var command = new CommandDocument
{
{"aggregate", collectionName},
{"pipeline", commandArray}
}
var result = database.RunCommandAs<AggregateResult<WidgetCollection>>(command).Result;
¿Por qué no da un paso más y depura el controlador usted mismo?El código fuente está aquí: https://github.com/mongodb/mongo-csharp-driver –
Buena llamada. Parece que trata de deserializar el elemento en la matriz, busca la cadena _t, luego la cadena _v, que no existe. He intentado buscar cuál es el propósito del elemento _v, pero no puedo encontrar nada. – anthv123
Estoy un poco confundido con respecto a lo que está usando en el parámetro de BsonSerializer.Deserialize ... ¿Está utilizando un Widget o un WidgetCollection? –