Я создаю собственный сериализатор для списка элементов, идея в том, что я буду избегать десериализации некоторых элементов на основе их значений.
Это прекрасно работает для большинства вызовов чтения / обновления, то есть
await collection.InsertOneAsync(entry);
await collection.FindAsync(x => x.Id == entry.Id);
await collection.FindOneAndUpdateAsync(x => x.Id == entry.Id, Builders<Outer>.Update.Set(x => x.Value, 5));
, но когда я выполняю вызов обновления, используя позиционный оператор,
var filter = Builders<Outer>.Filter.Where(x => x.Elements.Any(e => e.Id == elementId));
var update = Builders<Outer>.Update.Set(x => x.Elements[-1].Value, 5);
await collection.FindOneAndUpdateAsync(filter, update);
, происходит сбой со следующей ошибкой:
Unhandled Exception: System.ArgumentException: Property 'System.String Id' is not defined for type 'System.Object'
Parameter name: property
at System.Linq.Expressions.Expression.Property(Expression expression, PropertyInfo property)
at System.Linq.Expressions.Expression.MakeMemberAccess(Expression expression, MemberInfo member)
at System.Linq.Expressions.MemberExpression.Update(Expression expression)
at System.Linq.Expressions.ExpressionVisitor.VisitMember(MemberExpression node)
at MongoDB.Driver.Linq.Processors.SerializationBinder.VisitMember(MemberExpression node)
at System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor)
at MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression node)
at MongoDB.Driver.Linq.Processors.SerializationBinder.VisitBinary(BinaryExpression node)
at System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor)
at MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(Expression node)
at MongoDB.Driver.Linq.Processors.BinderHelper.BindWhere(PipelineExpression pipeline, IBindingContext bindingContext, LambdaExpression lambda)
at MongoDB.Driver.Linq.Processors.EmbeddedPipeline.MethodCallBinders.AnyBinder.Bind(PipelineExpression pipeline, EmbeddedPipelineBindingContext bindingContext, MethodCallExpression node, IEnumerable`1 arguments)
at MongoDB.Driver.Linq.Processors.MethodInfoMethodCallBinder`1.Bind(PipelineExpression pipeline, TBindingContext bindingContext, MethodCallExpression node, IEnumerable`1 arguments)
at MongoDB.Driver.Linq.Processors.CompositeMethodCallBinder`1.Bind(PipelineExpression pipeline, TBindingContext bindingContext, MethodCallExpression node, IEnumerable`1 arguments)
at MongoDB.Driver.Linq.Processors.PipelineBinderBase`1.BindMethodCall(MethodCallExpression node)
at MongoDB.Driver.Linq.Processors.EmbeddedPipeline.EmbeddedPipelineBinder.Bind(Expression node, IBindingContext parent)
at MongoDB.Driver.Linq.Processors.SerializationBinder.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](Expression`1 predicate, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOneAndUpdateOperation[TProjection](FilterDefinition`1 filter, UpdateDefinition`1 update, FindOneAndUpdateOptions`2 options)
at MongoDB.Driver.MongoCollectionImpl`1.FindOneAndUpdateAsync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, UpdateDefinition`1 update, FindOneAndUpdateOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass55_0`1.<FindOneAndUpdateAsync>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
at MongoFiltering.Program.Main(String[] args) in C:\Users\jeroen.vannevel\source\repos\MongoFiltering\MongoFiltering\Program.cs:line 51
at MongoFiltering.Program.<Main>(String[] args)
Я уменьшил его доследующий образецИз того, что я могу сказать, ваш пользовательский десериализатор на самом деле не нуждается в какой-либо работе - только его наличие нарушает условие фильтрации.
Ниже приведены модели, которые я использую, и пустой пользовательский сериализатор.Я создал MCVE здесь , который использует Mongo2Go для создания демона Монго на лету - вы можете просто его запустить.
public class Outer
{
public string Id { get; set; }
public int Value { get; set; }
[BsonSerializer(typeof(ElementsSerializer))]
public List<Element> Elements { get; set; }
}
public class Element
{
public string Id { get; set; }
public int Value { get; set; }
}
public class ElementsSerializer : EnumerableSerializerBase<List<Element>>
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, List<Element> value) => base.Serialize(context, args, value);
public override List<Element> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => base.Deserialize(context, args);
protected override void AddItem(object accumulator, object item) => ((List<Element>)accumulator).Add((Element)item);
protected override object CreateAccumulator() => new List<Element>();
protected override IEnumerable EnumerateItemsInSerializationOrder(List<Element> value) => value;
protected override List<Element> FinalizeResult(object accumulator) => (List<Element>)accumulator;
}