如何在 Microsoft Azure Functions 中将 DocumentDB 数据库输入绑定与服务总线触发器绑定和 BrokeredMessage 结合使用?

How do I use a DocumentDB database input binding with a Service Bus trigger binding and BrokeredMessage in Microsoft Azure Functions?

我正在编写一个简单的函数,它会在新消息到达服务总线队列时被触发。该函数的输入是一个 DocumentDB 文档。我需要访问文档中的值并将其输入到控制台日志中。

当您创建服务总线队列触发器绑定时,它会自动创建为:

public static void Run(string myQueueItem, TraceWriter log)
{
    log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
}

现在要访问我的数据库中的正确文档,根据 this page 可以设置绑定以便从队列消息中获取文档 ID:

id supports bindings similar to {queueTrigger}, which uses the string value of the queue message as the document Id.

这意味着您可以将消息发送到队列,然后像这样绑定到您的文档:

{
    "name": "inputDocument",
    "type": "documentDB",
    "databaseName": "MyDatabase",
    "collectionName": "MyCollection",
    "id" : "{myQueueItem}",//<<<
    "connection": "MyAccount_DOCUMENTDB",     
    "direction": "in"
}

到目前为止,一切似乎都按预期进行。但是,为了将消息发送到服务总线队列,您必须将其作为 BrokeredMessage 类型 (link) 发送。当您这样做时,您将无法再以字符串形式访问消息,从而使自动创建的函数变得无用。

可以通过以下方式使用 BrokeredMessages:

project.json:

{
    "frameworks": {
        "net46":{
            "dependencies": {
                "WindowsAzure.ServiceBus": "2.7.6"
            }
        }
    }
}

run.csx:

using Microsoft.ServiceBus.Messaging;
....
log.Info($"C# ID: {queueItem.GetBody<string>()})

但我一直没能找到如何将 {queueItem.GetBody<string>()} 传递到输入文档绑定的 id 属性中。所以我不能再使用上述方法通过 "id" : "{myQueueItem}" 绑定我的 documentdb 输入,因此无法从任何文档中读取任何值。

更完整的解释我的功能:

应用程序定期将新文档发送到 DocumentDB 数据库中。它与文档一起(在等待插入完成后)将带有新文档 ID 的消息发送到服务总线队列中。然后触发器连接到新文档并检查其中的整数值。如果该值大于 10,它会发送有关它的电子邮件通知。

我已成功创建并通过基于网络的编辑器手册运行 测试了它,其中一个文档的字符串 ID 作为测试输入。但是,当我尝试将它与自动发送文档和消息的应用程序一起使用时,我 运行 遇到了如上所述的 BrokeredMessage 问题。

下面是没有 BrokeredMessage 的工作函数的完整代码:

using System;
using System.Net;
using System.Net.Mail;

public static void Run(string queueItem, dynamic inputDocument, TraceWriter log)
{
    log.Info($"C# ID: {queueItem}, Value: {inputDocument.Value}");

    if (inputDocument.Value > 10)
    {
        var fromAddress = new MailAddress("---@gmail.com", "From ---");
        var toAddress = new MailAddress("---@gmail.com", "To ---");
        const string fromPassword = "---";
        const string subject = "Notification";
        const string body = "Temperature too high!";

        var smtp = new SmtpClient
        {
            Host = "smtp.gmail.com",
            Port = 587,
            EnableSsl = true,
            DeliveryMethod = SmtpDeliveryMethod.Network,
            UseDefaultCredentials = false,
            Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
        };
        using (var message = new MailMessage(fromAddress, toAddress)
        {
            Subject = subject,
            Body = body
        })
        {
            smtp.Send(message);
        }
    }
}

这是一个工作示例,展示了如何将 ServiceBus 消息作为 POCO 接收并绑定到它的属性。

如果您使用正确的 application/json 内容类型向队列发送消息,该函数将为您反序列化为 POCO,文档数据库输入绑定将绑定到 DocumentId 属性 并为您检索文档。您无需在 project.json 中添加任何内容即可工作。

function.json 文件:

{
  "bindings": [
    {
      "name": "input",
      "type": "serviceBusTrigger",
      "direction": "in",
      "queueName": "<your-queue.",
      "connection": "<your-connection>",
      "accessRights": "Manage"
    },
    {
      "type": "documentDB",
      "name": "document",
      "databaseName": "<your-db>",
      "collectionName": "<your-collection>",
      "id": "{DocumentId}",
      "connection": "<your-connection>",
      "direction": "in"
    }
  ]
}

函数代码:

using System;
using System.Threading.Tasks;

public class Input
{
    public string DocumentId { get; set; }
    public int Value { get; set; }
}

public static void Run(Input input, dynamic document, TraceWriter log)
{
    log.Info($"Message received (DocumentId: {input.DocumentId}, Value {input.Value})");
    log.Info($"Document read {document.id}");
}

对于 C# 函数,要使用绑定参数(例如 {DocumentId} 参数),触发器输入必须绑定到定义这些属性的 POCO 对象。

要发送电子邮件,您还可以查看我们的 SendGrid 输出绑定。我们在 "Samples" 下的门户中提供了完整的示例 "SendGrid-CSharp" :)