C# 调试DocumentDB触发器

C# 调试DocumentDB触发器,c#,azure,azure-cosmosdb,C#,Azure,Azure Cosmosdb,要测试DocumentDB中触发器的使用,请执行以下操作: 上传了示例post触发器 创建了一个元数据文档,其属性为“isMetadata”:true 使用C#执行一些文档写入,包括带有PostTriggerInclude=new List{“updateMetadata”} 不幸的是,当我的代码插入文档时,元数据文件就放在那里,0完全不受触发器的影响。我验证了触发器中的选择SQL,以确保它能够找到元数据文档来编辑它。似乎没有日志可供我进一步调查 如何调试DocumentDB触发器? (由于

要测试DocumentDB中触发器的使用,请执行以下操作:

  • 上传了示例post触发器
  • 创建了一个元数据文档,其属性为
    “isMetadata”:true
  • 使用C#执行一些文档写入,包括带有
    PostTriggerInclude=new List{“updateMetadata”}
不幸的是,当我的代码插入文档时,元数据文件就放在那里,0完全不受触发器的影响。我验证了触发器中的选择SQL,以确保它能够找到元数据文档来编辑它。似乎没有日志可供我进一步调查

如何调试DocumentDB触发器?

(由于问题可能是野餐,我的设置是否有明显的问题?)

元数据文档:

  {
    "id": "metadata",
    "isMetadata": true,
    "minSize": 0,
    "maxSize": 0,
    "totalSize": 0,
  }
代码段:

var docResp =   await client.CreateDocumentAsync(collectionUri, webhit,
                    new RequestOptions
                    {
                        PostTriggerInclude = new List<string> { "updateMetadata" }
                    }
                );
var docResp=await client.createDocumentSync(collectionUri、webhit、,
新的请求选项
{
PostTriggerInclude=新列表{“updateMetadata”}
}
);

在存储过程或触发器中,脚本抛出的所有错误都将被传输回客户端异常,并带有堆栈跟踪。因此,调试脚本的一种方法是使用throw new Error(…)作为脚本中的断点,单步执行脚本并在不同点进行抛出,以验证代码是否按预期运行

假设您使用的是分区集合。与存储过程一样,触发器的作用域是单个分区()。因此,触发器可以访问和更新的内容必须在运行触发器的分区内

在您的示例中,在不更改触发器脚本的情况下,您需要为每个分区键值预先创建一个元数据文档。然后,要获得集合的最终统计信息,您需要查询所有元数据文档(将有多个),并在客户端对这些元数据文档进行最终聚合

另一个选项是在触发器内自动创建元数据文档。这将避免创建多于必要的元数据文档,因为每个分区只需要一个元数据文档。以下是我对您的原始脚本的修改,用于创建:

   /**

    * This script runs as a trigger:

    * for each inserted document, look at document.size and update aggregate properties of metadata document: minSize, maxSize, totalSize.

    */

    function updateMetadata() {

        // HTTP error codes sent to our callback funciton by DocDB server.

        var ErrorCode = {

            RETRY_WITH: 449,

        }



        var collection = getContext().getCollection();

        var collectionLink = collection.getSelfLink();



        // Get the document from request (the script runs as trigger, thus the input comes in request).

        var doc = getContext().getRequest().getBody();



        // Check the doc (ignore docs with invalid/zero size and metaDoc itself) and call updateMetadata.

        if (!doc.isMetadata && doc.size != undefined && doc.size > 0) {

            getAndUpdateMetadata();

        }



        function getAndUpdateMetadata() {

            // Get the meta document. We keep it in the same collection. it's the only doc that has .isMetadata = true.

            var isAccepted = collection.queryDocuments(collectionLink, 'SELECT * FROM TestColl r WHERE r.isMetadata = true', function (err, feed, options) {

                if (err) throw err;

                var metaDoc;
                if (!feed || !feed.length) {
            // Create the meta doc for this partition, using the partition key value from the request document
                    metaDoc = {
                        "id": "metadata",
                        "isMetadata": true,
                        "minSize": 0,
                        "maxSize": 0,
                        "totalSize": 0,
                    }
                    metaDoc.partitionKey = doc.partitionKey;
                }
                else {
                    // Found the metadata document for this partition. So just use it
                    metaDoc = feed[0];
                }


                // Update metaDoc.minSize:

                // for 1st document use doc.Size, for all the rest see if it's less than last min.

                if (metaDoc.minSize == 0) metaDoc.minSize = doc.size;

                else metaDoc.minSize = Math.min(metaDoc.minSize, doc.size);



                // Update metaDoc.maxSize.

                metaDoc.maxSize = Math.max(metaDoc.maxSize, doc.size);



                // Update metaDoc.totalSize.

                metaDoc.totalSize += doc.size;



                // Update/replace the metadata document in the store.
                var isAccepted;
                if (!feed || !feed.length) {
            // Create the metadata document if it doesn't exist
                    isAccepted = collection.createDocument(collectionLink, metaDoc, function (err) {

                        if (err) throw err;

                        // Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again 

                        //       and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).

                        //       We have to take care of that on the client side.

                    });
                }
                else {
            // Replace the metadata document
                    isAccepted = collection.replaceDocument(metaDoc._self, metaDoc, function (err) {

                        if (err) throw err;

                        // Note: in case concurrent updates causes conflict with ErrorCode.RETRY_WITH, we can't read the meta again 

                        //       and update again because due to Snapshot isolation we will read same exact version (we are in same transaction).

                        //       We have to take care of that on the client side.

                     });
                }

                if (!isAccepted) throw new Error("The call replaceDocument(metaDoc) returned false.");
            });

            if (!isAccepted) throw new Error("The call queryDocuments for metaDoc returned false.");

        }

    }
希望这有帮助。如果您还有其他问题,请随时发回

谢谢


Lenning

我使用了这个修订版,使用Azure DocumentDB Studio我可以添加一个文档,并将UpdateMatadata作为PostTrigger。它添加文档并返回罚款,但有趣的是,如果我尝试“读取”任何内容,我会得到
Microsoft.Azure.Documents.DocumentClientException:Message:{“Errors”:[“指定的输入之一无效”]}ActivityId:706529a1-82b9-4ed1-a395-6090ddf91b50,请求URI:/apps/36834417-c2b8-4524-871e-e3247817af32/services/78da0810-31a5-45d3-bb94-8ef7a68e12cd/partitions/91e5e314-dc36-419e-84d8-fba2825499c9/replications/131157324155592025s
你好,斯蒂芬,你是如何“阅读”这个收藏的?从门户或我的C#代码中读取数据和元数据文档都没有问题。您执行的特定操作产生了一个错误,我们说触发器的操作类型无效。似乎您在尝试调用触发器时,您的操作不是创建、删除或替换。你能让我知道更多关于“读取”操作的信息吗?谢谢