Дерево выражений не поддерживается в UpdateOneAsync

При вызове UpdateOneAsync с помощью этой оболочки:

    public async Task<UpdateResult> UpdateDocument<T>(
        string sCollectionName, 
        Expression<Func<T, bool>> filter, 
        UpdateDefinition<T> update,
        bool bUpsert,
        System.Threading.CancellationToken cancellationToken
        )
    {
        IMongoDatabase db = _mongoClient.GetDatabase(_optionsMonitor.CurrentValue.databasename);

        IMongoCollection<T> collection = db.GetCollection<T>(sCollectionName);

        return await collection.UpdateOneAsync<T>(filter, update, new UpdateOptions() { IsUpsert = bUpsert }, cancellationToken);
    }

Вот так:

private async Task<Models.Errors> UpdateDbOnSyncServerToBoardUpdate(
        CancellationToken cancel,
        MongoDB.Bson.BsonDocument bsonDocConfigurationToUpdate,
        DateTime dtUpdated,
        string sId,
        int iObjectId,
        string sAppName,
        string sModelName
        )
    {
        MongoDB.Driver.UpdateResult updateResult = null;
        Models.Errors errors = null;

        try
        {
            updateResult = await _db.UpdateDocument<Models.Database.NodeBoardModel>(
                Constants.NodeBoardCollectionName,
                node => node.Id == sId && 
                node.RemoteBoard.apps.SingleOrDefault(
                    app => app.appname == sAppName).objects.
                    SingleOrDefault(model => model.name == sModelName).config_docs.
                    Any(config => config.config_id == iObjectId),
                MongoDB.Driver.Builders<Models.Database.NodeBoardModel>.Update.
                Set(
                    node => node.RemoteBoard.apps[-1].objects[-1].config_docs[-1].config_doc, bsonDocConfigurationToUpdate).
                Set(
                    node => node.RemoteBoard.apps[-1].objects[-1].config_docs[-1].config_dt, dtUpdated),
                false,
                cancel
                );

Я получаю исключение NotSupportedException:

The expression tree is not supported: {document}{RemoteBoard}{apps}.SingleOrDefault(app => (app.appname == "eACM")).objects.SingleOrDefault(model => (model.name == "tag")).config_docs

Я чувствую, что использую ключевое слово LINQ неправильно или таким образом, который не поддерживается MongoDb, но трудно точно сказать, в чем проблема.

Я ничего не могу сделать с трассировкой стека:

at MongoDB.Driver.Linq.Processors.EmbeddedPipeline.EmbeddedPipelineBinder.BindNonMethodCall(Expression node) at MongoDB.Driver.Linq.Processors.PipelineBinderBase1.BindPipeline(Expression node) at MongoDB.Driver.Linq.Processors.PipelineBinderBase1.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 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.Translators.PredicateTranslator.Translate[TDocument](Expression1 predicate, IBsonSerializer1 parameterSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.MongoCollectionImpl1.ConvertWriteModelToWriteRequest(WriteModel1 model, Int32 index) at System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable1 source, Func3 selector)+MoveNext() at System.Collections.Generic.List1.AddEnumerable(IEnumerable1 enumerable) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation..ctor(CollectionNamespace collectionNamespace, IEnumerable1 requests, MessageEncoderSettings messageEncoderSettings) at MongoDB.Driver.MongoCollectionImpl1.CreateBulkWriteOperation(IEnumerable1 requests, BulkWriteOptions options) at MongoDB.Driver.MongoCollectionImpl1.BulkWriteAsync(IClientSessionHandle session, IEnumerable1 requests, BulkWriteOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl1.UsingImplicitSessionAsync[TResult](Func2 funcAsync, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionBase1.UpdateOneAsync(FilterDefinition1 filter, UpdateDefinition1 update, UpdateOptions options, Func3 bulkWriteAsync) at WebApplication.Services.ConcreteDatabase.UpdateDocument[T](String sCollectionName, Expression1 filter, UpdateDefinition1 update, Boolean bUpsert, CancellationToken cancellationToken) in C:\GIT\app-manager\APIMM\ServerLevelConfiguration\WebApplication\Services\ConcreteDatabase.cs:line 131 at WebApplication.Services.SyncBoardDatabaseBackgroundService.UpdateDbOnSyncServerToBoardUpdate(CancellationToken cancel, BsonDocument bsonDocConfigurationToUpdate, DateTime dtUpdated, String sId, Int32 iObjectId, String sAppName, String sModelName) in C:\GIT\app-manager\APIMM\ServerLevelConfiguration\WebApplication\Services\SyncBoardDatabaseBackgroundService.cs:line 353

Классы моделей:

public class NodeBoardModel
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string Id { get; set; }

    [BsonElement]
    public NodeBoardRemoteModel RemoteBoard { get; set; }
}

public class NodeBoardRemoteModel
{
    [BsonElement]
    public List<NodeBoardAppModel> apps { get; set; }
}

public class NodeBoardAppModel
{
    [BsonElement]
    public string appname { get; set; }

    [BsonElement]
    public List<NodeBoardObjectModel> objects { get; set; }
}

public class NodeBoardObjectModel
{
    [BsonElement]
    public string name { get; set; }

    [BsonElement]
    public List<NodeBoardObjectConfigurationModel> config_docs { get; set; }
}

public class NodeBoardObjectConfigurationModel
{
    [BsonElement]
    public BsonDocument config_doc { get; set; }

    [BsonElement]
    public DateTime config_dt { get; set; }

    [BsonElement]
    public int config_id { get; set; }
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
2 462
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема начинается, когда вы пытаетесь построить свое утверждение Update. Как вы, наверное, знаете -1, переданный в качестве индекса, будет от переведено до $ позиционный оператор. документация говорит, что

The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

Кроме того, вы пытаетесь создать условие фильтрации с помощью SingleOrDefault, а драйвер .NET MongoDB не может преобразовать это в какой-либо оператор синтаксиса запроса MongoDB.

Как это исправить?

Вместо использования позиционного оператора вы можете попробовать использовать синтаксис позиционный фильтрующий оператор.

var filter = Builders<NodeBoardModel>.Filter.Eq(f => f.Id, sId);
var update = Builders<NodeBoardModel>.Update.Set("RemoteBoard.apps.$[app].objects.$[object].config_docs.$[configdoc].config_dt", dtUpdated);

var arrayFilters = new List<ArrayFilterDefinition>();
ArrayFilterDefinition<BsonDocument> appFilter = new BsonDocument("app.appname", new BsonDocument("$eq", sAppName));
ArrayFilterDefinition<BsonDocument> objectFilter = new BsonDocument("object.name", new BsonDocument("$eq", sModelName));
ArrayFilterDefinition<BsonDocument> configDocFilter = new BsonDocument("configdoc.config_id", new BsonDocument("$eq", iObjectId));

arrayFilters.AddRange(new[] { appFilter, objectFilter, configDocFilter });

var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };

var res = Col.UpdateOne(filter, update, updateOptions);

Большое спасибо. Я боролся с этим все утро.

Timothy John Laird 09.04.2019 20:48

Другие вопросы по теме