Compartir a través de

使用 Visual Studio Code 将 Azure Functions 连接到 Azure SQL 数据库

无需编写自己的集成代码,即可使用 Azure Functions 将 Azure 服务和其他资源连接到函数。 这些绑定表示输入和输出,在函数定义中声明。 绑定中的数据作为参数提供给函数。 触发器是一种特殊类型的输入绑定。 尽管一个函数只有一个触发器,但它可以有多个输入和输出绑定。 有关详细信息,请参阅 Azure Functions 触发器和绑定的概念

本文介绍如何使用 Visual Studio Code 将 Azure SQL 数据库连接到在前一篇快速入门文章中创建的函数。 添加到此函数的输出绑定会将 HTTP 请求中的数据写入到 Azure SQL 数据库中的一张表中。

在开始之前,必须先完成快速入门:使用 Visual Studio Code 在 Azure 中创建 C# 函数。 如果在该文章结束时清理了资源,请再次执行相应的步骤,以在 Azure 中重新创建函数应用和相关资源。

在开始之前,必须先完成快速入门:使用 Visual Studio Code 在 Azure 中创建 JavaScript 函数。 如果在该文章结束时清理了资源,请再次执行相应的步骤,以在 Azure 中重新创建函数应用和相关资源。

在开始之前,必须先完成快速入门:使用 Visual Studio Code 在 Azure 中创建 Python 函数。 如果在该文章结束时清理了资源,请再次执行相应的步骤,以在 Azure 中重新创建函数应用和相关资源。

有关 Azure SQL 绑定和适用于 Azure Functions 的触发器设置的详细信息,请参阅 Azure Functions 文档。

创建 Azure SQL 数据库

  1. 请按照 Azure SQL 数据库创建快速入门中介绍的步骤,创建一个无服务器 Azure SQL 数据库。 数据库可以是空的,也可以使用示例数据集 AdventureWorksLT 创建。

  2. 根据提示提供以下信息:

    Prompt 选择
    资源组 选择在前面的文章中创建函数应用的资源组。
    数据库名称 输入 mySampleDatabase
    服务器名称 为服务器输入唯一名称。 我们无法提供要使用的确切服务器名称,因为对于 Azure 中的所有服务器,服务器名称必须全局唯一,而不只是在订阅中唯一。
    身份验证方法 选择“SQL Server 身份验证”
    服务器管理员登录名 输入 azureuser
    密码 输入满足复杂性要求的密码。
    允许 Azure 服务和资源访问此服务器 选择 “是”
  3. 完成创建后,导航到 Azure 门户中的“数据库”边栏选项卡,在“设置”下选择“连接字符串”。 复制用于进行 SQL 身份验证ADO.NET 连接字符串。 将连接字符串粘贴到一个临时文档中,以备稍后使用。

    在 Azure 门户中复制 Azure SQL 数据库连接字符串的屏幕截图。

  4. 创建一个表来存储来自 HTTP 请求的数据。 在 Azure 门户,导航到“数据库”边栏选项卡,然后选择“查询编辑器”。 输入以下查询以创建名为 dbo.ToDo 的新表:

CREATE TABLE dbo.ToDo (
    [Id] UNIQUEIDENTIFIER PRIMARY KEY,
    [order] INT NULL,
    [title] NVARCHAR(200) NOT NULL,
    [url] NVARCHAR(200) NOT NULL,
    [completed] BIT NOT NULL
);
  1. 检查服务器的防火墙设置,验证 Azure Functions 能够访问 Azure SQL 数据库。 导航到 Azure 门户的服务器边栏选项卡,在“安全性”下,选择“网络”。 应查看“允许 Azure 服务和资源访问此服务器”的例外情况。

    在 Azure 门户中检查 Azure SQL 数据库防火墙设置的屏幕截图。

更新函数应用设置

前一篇快速入门文章中,你已在 Azure 中创建了一个函数应用。 在本文中,你将学习如何更新应用,将数据写入到刚刚创建的 Azure SQL 数据库中。 要连接到 Azure SQL 数据库,必须将其连接字符串添加到应用设置。 然后,将新设置下载到 local.settings.json 文件,这样就可以在本地运行时可以连接到 Azure SQL 数据库。

  1. 编辑先前创建后保存在临时文档中的连接字符串。 将 Password 的值替换为创建 Azure SQL 数据库时使用的密码。 复制更新后的连接字符串。

  2. 再次按 Ctrl/Cmd+shift+P 打开命令面板,然后搜索并运行命令 Azure Functions: Add New Setting...

  3. 选择你在前一篇文章中创建的函数应用。 根据提示提供以下信息:

    Prompt 选择
    输入新应用设置名称 键入 SqlConnectionString
    输入“SqlConnectionString”的值 粘贴你刚刚复制的 Azure SQL 数据库的连接字符串。

    这会在 Azure 的函数应用中创建一个名为 connection SqlConnectionString 的应用程序设置。 现在可以将此设置下载到 local.settings.json 文件中。

  4. 再次按 Ctrl/Cmd+shift+P 打开命令面板,然后搜索并运行命令 Azure Functions: Download Remote Settings...

  5. 选择你在前一篇文章中创建的函数应用。 选择“全是”覆盖现有本地设置。

这会将 Azure 中的所有设置下载到本地项目,包括新的连接字符串设置。 下载的大多数设置不会在本地运行时使用。

注册绑定扩展

由于你使用 Azure SQL 输出绑定,因此在运行项目之前,必须安装对应的绑定扩展。

除了 HTTP 和计时器触发器,绑定将实现为扩展包。 在终端窗口中运行以下 dotnet add package 命令,将 Azure SQL 扩展包添加到项目中。

dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Sql

项目已配置为使用扩展捆绑包,因此会自动安装一组预定义的扩展包。

在项目根目录下的 host.json 文件中启用扩展捆绑包,如下所示:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  },
  "concurrency": {
    "dynamicConcurrencyEnabled": true,
    "snapshotPersistenceEnabled": true
  }
}

:::

现在,你可以将 Azure SQL 输出绑定添加到项目。

添加输出绑定

在 Functions 中,每种类型的绑定都需要一个 directiontype,以及要在 function.json 文件中定义的唯一 name。 定义这些属性的方式取决于函数应用的语言。

打开 HttpExample.cs 项目文件并添加以下 ToDoItem 类,该类定义写入数据库的对象:

namespace AzureSQL.ToDo
{
    public class ToDoItem
    {
        public Guid Id { get; set; }
        public int? order { get; set; }
        public string title { get; set; }
        public string url { get; set; }
        public bool? completed { get; set; }
    }
}

在 C# 类库项目中,绑定被定义为函数方法上的绑定属性。 然后,基于这些属性自动生成 Functions 所需的 function.json 文件。

打开 HttpExample.cs 项目文件并添加以下输出类型类,该类定义函数会为 HTTP 响应和 SQL 输出的组合对象:

public static class OutputType
{
    [SqlOutput("dbo.ToDo", connectionStringSetting: "SqlConnectionString")]
    public ToDoItem ToDoItem { get; set; }
    public HttpResponseData HttpResponse { get; set; }
}

将 using 语句添加到文件顶部的 Microsoft.Azure.Functions.Worker.Extensions.Sql 库:

using Microsoft.Azure.Functions.Worker.Extensions.Sql;

绑定属性直接在代码中定义。 Azure SQL 输出配置描述了 Azure SQL输出绑定必需的字段。

对于此 MultiResponse 方案,你需要向函数添加 extraOutputs 输出绑定。

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  extraOutputs: [sendToSql],
  handler: async (request, context) => {

将以下属性添加到绑定配置:

const sendToSql = output.sql({
  commandText: 'dbo.ToDo',
  connectionStringSetting: 'SqlConnectionString',
});

直接在 function_app.py 文件中定义绑定属性。 使用 generic_output_binding 修饰器添加 Azure SQL 输出绑定

@app.generic_output_binding(arg_name="toDoItems", type="sql", CommandText="dbo.ToDo", ConnectionStringSetting="SqlConnectionString"
    data_type=DataType.STRING)

在这段代码中,arg_name 识别代码中引用的绑定参数,type 表示输出绑定是一个 SQL 输出绑定,CommandText 是绑定要写入的表,ConnectionStringSetting 则是包含 Azure SQL 连接字符串的应用程序设置的名称。 该连接字符串位于 local.settings.json 文件中的 SqlConnectionString 设置中。

添加使用输出绑定的代码

使用下面的代码替换现有 Run 方法:

[Function("HttpExample")]
public static OutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger("HttpExample");
    logger.LogInformation("C# HTTP trigger function processed a request.");

    var message = "Welcome to Azure Functions!";

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    response.WriteString(message);

    // Return a response to both HTTP trigger and Azure SQL output binding.
    return new OutputType()
    {
         ToDoItem = new ToDoItem
        {
            id = System.Guid.NewGuid().ToString(),
            title = message,
            completed = false,
            url = ""
        },
        HttpResponse = response
    };
}

添加使用 context 上的 extraInputs 输出绑定对象将 JSON 文档发送到命名输出绑定函数 sendToSql 的代码。 请在 return 语句之前添加此代码。

      const data = JSON.stringify([
        {
          // create a random ID
          Id: crypto.randomUUID(),
          title: name,
          completed: false,
          url: '',
        },
      ]);

      // Output to Database
      context.extraOutputs.set(sendToSql, data);

若要利用 crypto 模块,请将以下行添加到文件顶部:

const crypto = require("crypto");

此时,你的函数应如下所示:

const { app, output } = require('@azure/functions');
const crypto = require('crypto');

const sendToSql = output.sql({
  commandText: 'dbo.ToDo',
  connectionStringSetting: 'SqlConnectionString',
});

app.http('HttpExample', {
  methods: ['GET', 'POST'],
  extraOutputs: [sendToSql],
  handler: async (request, context) => {
    try {
      context.log(`Http function processed request for url "${request.url}"`);

      const name = request.query.get('name') || (await request.text());

      if (!name) {
        return { status: 404, body: 'Missing required data' };
      }

      // Stringified array of objects to be inserted into the database
      const data = JSON.stringify([
        {
          // create a random ID
          Id: crypto.randomUUID(),
          title: name,
          completed: false,
          url: '',
        },
      ]);

      // Output to Database
      context.extraOutputs.set(sendToSql, data);

      const responseMessage = name
        ? 'Hello, ' +
          name +
          '. This HTTP triggered function executed successfully.'
        : 'This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.';

      // Return to HTTP client
      return { body: responseMessage };
    } catch (error) {
      context.log(`Error: ${error}`);
      return { status: 500, body: 'Internal Server Error' };
    }
  },
});

按以下代码所示更新 HttpExample\function_app.py。 将 toDoItems 参数添加到函数定义,并将 toDoItems.set() 添加到 if name: 语句下:

import azure.functions as func
import logging
from azure.functions.decorators.core import DataType
import uuid

app = func.FunctionApp()

@app.function_name(name="HttpTrigger1")
@app.route(route="hello", auth_level=func.AuthLevel.ANONYMOUS)
@app.generic_output_binding(arg_name="toDoItems", type="sql", CommandText="dbo.ToDo", ConnectionStringSetting="SqlConnectionString",data_type=DataType.STRING)
def test_function(req: func.HttpRequest, toDoItems: func.Out[func.SqlRow]) -> func.HttpResponse:
     logging.info('Python HTTP trigger function processed a request.')
     name = req.get_json().get('name')
     if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

     if name:
        toDoItems.set(func.SqlRow({"Id": str(uuid.uuid4()), "title": name, "completed": False, "url": ""}))
        return func.HttpResponse(f"Hello {name}!")
     else:
        return func.HttpResponse(
                    "Please pass a name on the query string or in the request body",
                    status_code=400
                )

在本地运行函数

Visual Studio Code 与 Azure Functions Core Tools 相集成,便于你在发布到 Azure 之前在本地开发计算机上运行此项目。

  1. 若要调用函数,请按 F5 启动函数应用项目。 “终端”面板将显示 Core Tools 的输出。 应用将在“终端”面板中启动。 可以看到 HTTP 触发函数的 URL 终结点在本地运行。

    本地函数 Visual Studio Code 输出的屏幕截图。

    如果在 Windows 上运行时遇到问题,请确保用于 Visual Studio Code 的默认终端未设置为“WSL Bash”。

  2. 运行 Core Tools 后,转到“Azure: Functions”区域。 在“Functions”下,展开“本地项目”>“Functions” 。 右键单击 (Windows) 或按 Ctrl - 单击 (macOS) HttpExample 函数,然后选择“立即执行函数...”。

    Visual Studio Code 中的“立即执行函数”的屏幕截图。

  3. 在“输入请求正文”中,按 Enter 向函数发送请求消息。

  4. 当函数在本地执行并返回响应时,Visual Studio Code 中将引发通知。 函数执行的相关信息将显示在“终端”面板中。

  5. 按 Ctrl + C 停止 Core Tools 并断开调试器的连接

在本地运行函数

  1. 与上一篇文章中所述,按 F5 启动函数应用项目和 Core Tools。

  2. 运行 Core Tools 后,转到“Azure:Functions”区域。 在“Functions”下,展开“本地项目”>“Functions” 。 右键单击 HttpExample 函数(在 Mac 按 Ctrl-单击),然后选择“立即执行函数...”。

    Visual Studio Code 中的“立即执行函数”菜单项的屏幕截图。

  3. 在“输入请求正文”中,你将看到请求消息正文值 。 按 Enter 将此请求消息发送给函数。

  4. 返回响应后,按 Ctrl + C 停用 Core Tools。

验证信息已写入数据库

  1. 在 Azure 门户,返回到 Azure SQL 数据库并选择“查询编辑器”。

    登录到 Azure 门户中的查询编辑器的屏幕截图。

  2. 连接到数据库,并展开左侧对象资源管理器中的“”节点。 右键单击 dbo.ToDo 表,然后选择“选择前 1000 行”。

  3. 验证输出绑定是否已将新信息写入数据库。

重新部署并验证更新的应用

  1. 在 Visual Studio Code 中,按 F1 打开命令面板。 在命令面板中,搜索并选择 Azure Functions: Deploy to function app...

  2. 选择你在第一篇文章中创建的函数应用。 由于你要将项目重新部署到同一个应用,因此请选择“部署”以关闭关于覆盖文件的警告。

  3. 部署完成后,可再次使用“立即执行函数...”功能在 Azure 中触发该函数。

  4. 再次检查数据是否已写入 Azure SQL 数据库,确认输出绑定再次生成新的 JSON 文档。

清理资源

在 Azure 中,“资源”是指函数应用、函数、存储帐户等。 这些资源可以组合到资源组中,删除该组即可删除组中的所有内容。

已创建完成这些快速入门所需的资源。 这些资源可能需要付费,具体取决于帐户状态服务定价。 如果不再需要这些资源,请参阅下面介绍的资源删除方法:

  1. 在 Visual Studio Code 中,按 F1 打开命令面板。 在命令面板中,搜索并选择 Azure: Open in portal

  2. 选择你的函数应用,然后按 Enter。 随即将在 Azure 门户中打开函数应用页面。

  3. 在“概览”选项卡中,选择“资源组”旁边的命名链接。

    从函数应用页选择要删除的资源组的屏幕截图。

  4. 在“资源组”页上查看所包括的资源的列表,然后验证这些资源是否是要删除的。

  5. 选择“删除资源组”,然后按说明操作。

    可能需要数分钟才能删除完毕。 完成后会显示一个通知,持续数秒。 也可以选择页面顶部的钟形图标来查看通知。

后续步骤

现已更新 HTTP 触发的函数,使其将数据写入 Azure SQL 数据库。 现在,可以详细了解如何使用 Visual Studio Code 开发 Functions: