Azure函数使用Binder

时间:2017-02-02 16:23:50

标签: azure azure-cosmosdb azure-functions

关于Azure功能的previous post的关注问题。我需要使用命令式绑定器(Binder)更新DocumentDB中的文档。我不太了解documentation而且我找不到任何示例(我或多或少地找到了一种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中添加一个输出,但是编译器抱怨它并且文档说明你不应该有。

我错过了什么?

2 个答案:

答案 0 :(得分:5)

Mathew的示例(使用DocumentClient)有效,但我想澄清使用Binder和输出绑定的另一种方式。

你遇到了两个问题:

  1. 每次请求子对象时,Document动态实现似乎都会返回一个新的对象实例。这与函数无关,但解释了为什么document.child.value = 200不起作用。您正在更新一个实际上未附加到文档的子实例。我将尝试使用DocumentDb人员仔细检查这一点,但这令人困惑。解决此问题的一种方法是请求JObject而不是dynamic。我的代码就是这样做的。

  2. 正如@mathewc所指出的那样,Binder不会自动更新文档。我们将在他提交的问题中跟踪这一点。相反,您可以使用IAsyncCollector<dynamic>的输出绑定来更新文档。在幕后,我们将调用InsertOrReplaceDocumentAsync,这将更新文档。

  3. 这是一个适合我的完整示例:

    代码:

    #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
    }
    

答案 1 :(得分:2)

是的,我相信这里有一个问题,我在我们的仓库中记录了一个错误here来跟踪它。

要解决此问题,我们可以直接绑定并使用DocumentClient来执行更新,例如:

public static async Task Run(
    string input, Binder binder, DocumentClient client, TraceWriter log)
{
    var docId = "c31d48aa-d74b-46a3-8ba6-0d4c6f288559";
    var document = await binder.BindAsync<JObject>(
                new DocumentDBAttribute("ItemDb", "ItemCollection")
    {
        ConnectionStringSetting = "<mydb>",
        Id = docId
    });

    log.Info("Item before: " +  document.ToString());
    document["text"] = "Modified!";

    var docUri = UriFactory.CreateDocumentUri("ItemDb", "ItemCollection", docId);
    await client.ReplaceDocumentAsync(docUri, document);
}

但是,一旦您直接使用此DocumentClient,可能会直接将其用于您的所有操作和通话。例如:

public static async Task Run(
    string input, DocumentClient client, TraceWriter log)
{
    var docId = "c31d48aa-d74b-46a3-8ba6-0d4c6f288559";
    var docUri = UriFactory.CreateDocumentUri("ItemDb", "ItemCollection", docId);

    var response = await client.ReadDocumentAsync(docUri);
    dynamic document = response.Resource;

    log.Info("Value: " +  dynamic.text);
    document.text = "Modified!"; 

    await client.ReplaceDocumentAsync(docUri, document);
}