Azure Functions使用Binder更新DocumentDb文档 [英] Azure Functions Update DocumentDb document with Binder

查看:45
本文介绍了Azure Functions使用Binder更新DocumentDb文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对以前的帖子关于Azure Functions的追问.我需要使用命令式联编程序(Binder)更新DocumentDB中的文档.我不太了解文档,但我找不到任何示例(我或多或少地找到了一种示例,即TextWriter).该文档说,我找不到此类示例,因此可以绑定到"out T".

在运行函数之前,假设文档如下所示:

{
    child: {
        value: 0
    }
}

函数看起来像这样:

var document = await binder.BindAsync<dynamic>(new DocumentDBAttribute("myDB", "myCollection")
{
    ConnectionStringSetting = "my_DOCUMENTDB",
    Id = deviceId
});

log.Info($"C# Event Hub trigger function processed a message: document: { document }");

document.value = 100;
document.child.value = 200;

log.Info($"Updated document: { document }");

根据第二个日志记录行,该文档未正确更新.子项不会更新(从商店中读取时已存在)并添加了值.无论哪种方式,都不会持久存在.我曾尝试在function.json中添加一个Output,但是编译器对此有所抱怨,并且文档指出您不应有任何内容.

我想念什么?

解决方案

Mathew的示例(使用DocumentClient)可以工作,但是我想阐明使用Binder和输出绑定进行操作的另一种方法.

您遇到了两个问题:

  1. dynamic的Document实现似乎在每次您请求子对象时都返回一个新的对象实例.这与功能无关,但解释了为什么document.child.value = 200不起作用.您正在更新一个未实际附加到文档的子实例.我将尝试与DocumentDb人员再次确认,但这令人困惑.解决此问题的一种方法是请求JObject而不是dynamic.我下面的代码可以做到这一点.

  2. 正如@mathewc指出的那样,Binder不会自动更新文档.我们将在他提出的问题中进行跟踪.而是可以使用带有IAsyncCollector<dynamic>的输出绑定来更新文档.在幕后,我们将调用InsertOrReplaceDocumentAsync,它将更新文档.

以下是对我有用的完整示例:

代码:

#r "Microsoft.Azure.WebJobs.Extensions.DocumentDB"
#r "Newtonsoft.Json"

using System;
using Newtonsoft.Json.Linq;

public static async Task Run(string input, Binder binder, IAsyncCollector<dynamic> collector, TraceWriter log)
{        
    string deviceId = "0a3aa1ff-fc76-4bc9-9fe5-32871d5f451b";
    dynamic document = await binder.BindAsync<JObject>(new DocumentDBAttribute("ItemDb", "ItemCollection")
    {
        ConnectionStringSetting = "brettsamfunc_DOCUMENTDB",
        Id = deviceId
    });

    log.Info($"C# Event Hub trigger function processed a message: document: { document }");

    document.value = 100;
    document.child.value = 200;

    await collector.AddAsync(document);
    log.Info($"Updated document: { document }");
}

绑定:

{
  "type": "documentDB",
  "name": "collector",
  "connection": "brettsamfunc_DOCUMENTDB",
  "direction": "out",
  "databaseName": "ItemDb",
  "collectionName": "ItemCollection",
  "createIfNotExists": false
}

A follow-question to my previous post about Azure Functions. I need to update a document in DocumentDB using the imperative binder (Binder). I don't really understand the documentation and I can't find any examples (I more or less find one kind of example which is the TextWriter one). The documentation says I can bind to "out T" by I find no examples of this.

Say that the document looks like this before running the function:

{
    child: {
        value: 0
    }
}

And the functions looks like this:

var document = await binder.BindAsync<dynamic>(new DocumentDBAttribute("myDB", "myCollection")
{
    ConnectionStringSetting = "my_DOCUMENTDB",
    Id = deviceId
});

log.Info($"C# Event Hub trigger function processed a message: document: { document }");

document.value = 100;
document.child.value = 200;

log.Info($"Updated document: { document }");

According to the second logging row, the document isn't properly updated. The child is not updated (which existed when read from the store) and value is added. Either way, nothing is persisted. I've tried adding an Output in the function.json, but the compiler complains about it and the documentation states that you shouldn't have any.

What am I missing?

解决方案

Mathew's sample (using DocumentClient) works, but I wanted to clarify the other way you can do it with Binder and an output binding.

You're bumping into two issues:

  1. The Document implementation of dynamic appears to return a new object instance every time you request a child object. This isn't related to Functions, but explains why document.child.value = 200 doesn't work. You are updating one instance of child that is not actually attached to the document. I'll try to double-check this with DocumentDb folks, but that is confusing. One way around this is to request a JObject instead of a dynamic. My code below does that.

  2. As @mathewc pointed out, Binder does not auto-update the document. We'll track that in the issue he filed. Instead, you can use an output binding with IAsyncCollector<dynamic> to update the document. Behind-the-scenes we'll call InsertOrReplaceDocumentAsync, which will update the document.

Here's a full sample that worked for me:

Code:

#r "Microsoft.Azure.WebJobs.Extensions.DocumentDB"
#r "Newtonsoft.Json"

using System;
using Newtonsoft.Json.Linq;

public static async Task Run(string input, Binder binder, IAsyncCollector<dynamic> collector, TraceWriter log)
{        
    string deviceId = "0a3aa1ff-fc76-4bc9-9fe5-32871d5f451b";
    dynamic document = await binder.BindAsync<JObject>(new DocumentDBAttribute("ItemDb", "ItemCollection")
    {
        ConnectionStringSetting = "brettsamfunc_DOCUMENTDB",
        Id = deviceId
    });

    log.Info($"C# Event Hub trigger function processed a message: document: { document }");

    document.value = 100;
    document.child.value = 200;

    await collector.AddAsync(document);
    log.Info($"Updated document: { document }");
}

binding:

{
  "type": "documentDB",
  "name": "collector",
  "connection": "brettsamfunc_DOCUMENTDB",
  "direction": "out",
  "databaseName": "ItemDb",
  "collectionName": "ItemCollection",
  "createIfNotExists": false
}

这篇关于Azure Functions使用Binder更新DocumentDb文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆