【问题标题】:Expression tree is not supported on UpdateOneAsyncUpdateOneAsync 不支持表达式树
【发布时间】:2019-08-31 00:58:11
【问题描述】:

在调用 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:

不支持表达式树:{document}{RemoteBoard}{apps}.SingleOrDefault(app => (app.appname == "eACM")).objects.SingleOrDefault(model => (model.name == "标签")).config_docs

我感觉我使用了错误的 LINQ 关键字,或者 MongoDb 不支持的方式,但很难准确判断问题出在哪里。

我无法对堆栈跟踪进行任何处理:

在 MongoDB.Driver.Linq.Processors.EmbeddedPipeline.EmbeddedPipelineBinder.BindNonMethodCall(表达式节点) 在 MongoDB.Driver.Linq.Processors.PipelineBinderBase1.BindPipeline(Expression node) at MongoDB.Driver.Linq.Processors.PipelineBinderBase1.BindMethodCall(MethodCallExpression 节点) 在 MongoDB.Driver.Linq.Processors.EmbeddedPipeline.EmbeddedPipelineBinder.Bind(表达式节点,IBindingContext 父级) 在 MongoDB.Driver.Linq.Processors.SerializationBinder.VisitMethodCall(MethodCallExpression 节点) 在 System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor 访问者) 在 MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(表达式节点) 在 System.Linq.Expressions.ExpressionVisitor.VisitBinary(BinaryExpression 节点) 在 MongoDB.Driver.Linq.Processors.SerializationBinder.VisitBinary(BinaryExpression 节点) 在 System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor 访问者) 在 MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(表达式节点) 在 MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate[TDocument](Expression1 predicate, IBsonSerializer1 parameterSerializer, IBsonSerializerRegistry serializerRegistry) 在 MongoDB.Driver.MongoCollectionImpl1.ConvertWriteModelToWriteRequest(WriteModel1 模型,Int32 索引) 在 System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable1 source, Func3 选择器)+MoveNext() 在 System.Collections.Generic.List1.AddEnumerable(IEnumerable1 可枚举) 在 System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation..ctor(CollectionNamespace collectionNamespace, IEnumerable1 请求,MessageEncoderSettings messageEncoderSettings) 在 MongoDB.Driver.MongoCollectionImpl1.CreateBulkWriteOperation(IEnumerable1 请求,BulkWriteOptions 选项) 在 MongoDB.Driver.MongoCollectionImpl1.BulkWriteAsync(IClientSessionHandle session, IEnumerable1 请求,BulkWriteOptions 选项,CancellationToken cancelToken) 在 MongoDB.Driver.MongoCollectionImpl1.UsingImplicitSessionAsync[TResult](Func2 funcAsync,CancellationToken cancelToken) 在 MongoDB.Driver.MongoCollectionBase1.UpdateOneAsync(FilterDefinition1 过滤器,UpdateDefinition1 update, UpdateOptions options, Func3 bulkWriteAsync) 在 C:\GIT\app-manager\APIMM\ServerLevelConfiguration\WebApplication\Services\ConcreteDatabase.cs 中的 WebApplication.Services.ConcreteDatabase.UpdateDocument[T](String sCollectionName, Expression1 filter, UpdateDefinition1 update, Boolean bUpsert, CancellationToken cancelToken):第 131 行 在 C:\GIT\app-manager\APIMM\ServerLevelConfiguration\WebApplication\Services\SyncBoardDatabaseBackgroundService 中的 WebApplication.Services.SyncBoardDatabaseBackgroundService.UpdateDbOnSyncServerToBoardUpdate(CancellationToken cancel, BsonDocument bsonDocConfigurationToUpdate, DateTime dtUpdated, String sId, Int32 iObjectId, String sAppName, String sModelName)。 cs:第 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; }
}

【问题讨论】:

    标签: c# mongodb linq mongodb-.net-driver


    【解决方案1】:

    当您尝试构建 Update 语句时,问题就开始了。您可能知道作为索引传递的-1 将是translated 到$ positional operator。 documentation 这么说

    位置 $ 运算符不能用于遍历多个数组的查询,例如遍历嵌套在其他数组中的数组的查询,因为 $ 占位符的替换是单个值

    此外,您正在尝试使用 SingleOrDefault 构建过滤条件,而 .NET MongoDB 驱动程序无法将其转换为任何 MongoDB 查询语法运算符。

    如何解决?

    您可以尝试使用positional filtered operator 语法,而不是使用位置运算符。

    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);
    

    【讨论】:

    • 非常感谢。我整个上午都在为此奋斗。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多