You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cosmos DB嵌套Individual Task部分更新遇对象未实例化错误求助

Cosmos DB嵌套JSON文档Patch更新报错:Object Not Set To An Instance Of An Object

问题背景

尝试更新Cosmos DB中存储的JSON文档里嵌套的IndividualTask对象,使用PatchOperation.Set或PatchOperation.Replace均抛出**"Object Not Set To An Instance Of An Object"**错误。已提前查询获取IndividualTaskSets和IndividualTask的数组索引(因它们位置不固定),同时使用过滤谓词定位目标IndividualTask(一个IndividualTaskSets下包含多个该对象)。

数据模型示例

{
  "GroupTask": [
    {
      "_type": null,
      "GroupTaskID": "GUID",
      "GroupTaskTitle": null,
      "GroupTaskDescription": null,
      "IndividualTaskSets": [
        {
          "SETID": "GUID",
          "CreatedBy": "",
          "CreatedDate": "0001-01-01T00:00:00",
          "IndividualTask": [
            {
              "IndividualTaskID": "GUID",
              "TaskStatus": "",
              "TaskTitle": "",
              "TaskType": "",
              "TaskDescription": "",
              "TaskNotes": "",
              "Priority": "Normal",
              "CreatedBy": "",
              "CreatedDate": "0001-01-01T00:00:00"
            }
          ]
        }
      ]
    }
  ],
  "CaseID": "GUID",
  "TenantID": "testtenant0004",
  "id": "GUID",
  "TaskID": "GUID"
}

使用的过滤谓词字符串

"FROM Task t JOIN g in t.GroupTask JOIN its IN g.IndividualTaskSets JOIN it IN its.IndividualTask WHERE it.IndividualTaskID ='" + itid + "'"

更新方法代码

public async Task<string> UpdateIT(ReturnTaskObject rto, IndividualTask updatedIT, string path)
{
    try
    {
        PatchItemRequestOptions patchItemRequestOptions = new PatchItemRequestOptions
        {
            FilterPredicate = path
        };
        ItemResponse<IndividualTask> response = await container.PatchItemAsync<IndividualTask>(
            id: rto.id, 
            partitionKey: new Microsoft.Azure.Cosmos.PartitionKey(rto.taskid),
            patchOperations: new[] { PatchOperation.Set("/IndividualTaskSets/" + rto.individualtasksetidorindex + "/IndividualTask/" + rto.individualtaskidorindex + "/", updatedIT)},
            // 曾尝试去掉过滤谓词,结果报错相同
            // patchOperations: new[] { PatchOperation.Replace("/GroupTask/0/IndividualTaskSets/" + rto.individualtasksetidorindex + "/IndividualTask/" + rto.individualtaskidorindex + "/", updatedIT) }
            requestOptions: patchItemRequestOptions
        );
        string status = response.StatusCode.ToString();
        return status;
    }
    catch (Exception e)
    {
        return e.Message;
    }
}

完整堆栈跟踪

at CMaaS.Task.Service.DBUtil.UpdateIT(ReturnTaskObject rto, IndividualTask updatedIT, String path)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at CMaaS.Task.Service.DBUtil.UpdateIT(ReturnTaskObject rto, IndividualTask updatedIT, String path) at System.Dynamic.UpdateDelegates.UpdateAndExecute4[T0,T1,T2,T3,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
   at CMaaS.Task.Function.FunctionTaskController.RunUpdateIndividualTaskSetAsync(HttpRequest req, ILogger log)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at CMaaS.Task.Function.FunctionTaskController.RunUpdateIndividualTaskSetAsync(HttpRequest req, ILogger log)
   at lambda_method149(Closure , FunctionTaskController , Object[] )
   at Microsoft.Azure.WebJobs.Host.Executors.TaskMethodInvoker`2.InvokeAsync(TReflected instance, Object[] arguments)
   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync(Object instance, Object[] arguments)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
   at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c.<OutputCorrelationEtwEvent>b__6_0(Action innerContinuation, Task continuationIdTask)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke()
   at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.RunAction(Object state)
   at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

排查与解决要点

  1. 修复Patch路径完整性
    原始代码中第一个Patch路径/IndividualTaskSets/...错误,因为IndividualTaskSets并非根节点直接属性,而是嵌套在GroupTask数组内。正确路径需包含GroupTask的索引层级,比如:

    PatchOperation.Set($"/GroupTask/{rto.groupTaskIndex}/IndividualTaskSets/{rto.individualtasksetidorindex}/IndividualTask/{rto.individualtaskidorindex}", updatedIT)
    

    确保你已获取到GroupTask数组的正确索引(不能硬编码为0,需通过查询动态获取)。

  2. 过滤谓词语法修正
    PatchItemRequestOptions.FilterPredicate仅需要WHERE子句的内容,而非完整SQL语句。正确写法应为:

    FilterPredicate = $"it.IndividualTaskID = '{itid}'"
    

    注意:该谓词是用来判断是否执行Patch操作(当文档满足条件时才更新),而非定位嵌套对象,嵌套对象的定位仍需依赖Patch路径中的数组索引。

  3. 验证索引有效性
    确认rto.individualtasksetidorindex和rto.individualtaskidorindex是数字类型的数组索引,而非GUID字符串。Patch路径中数组元素需通过索引位置访问,无法直接用ID定位。

  4. 泛型参数匹配文档类型
    PatchItemAsync的泛型参数应与整个文档的类型一致,而非嵌套的IndividualTask。比如如果你的文档类型是TaskDocument,则应改为:

    ItemResponse<TaskDocument> response = await container.PatchItemAsync<TaskDocument>(...)
    

    使用错误的泛型类型可能导致序列化/反序列化异常,间接引发空引用错误。

内容的提问来源于stack exchange,提问作者Kuruption

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:36:32