通过


你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:在 Azure Static Web Apps 中添加 MySQL 数据库连接(预览版)

本教程介绍如何将 Azure Database for MySQL 灵活服务器数据库连接到静态 Web 应用。 配置后,您可以向内部 /data-api 终结点发出 REST 或 GraphQL 请求以操作数据,而无需编写后端代码。

为简单起见,本教程介绍如何使用 Azure 数据库进行本地开发,但也可以将本地数据库服务器用于本地开发需求。

注释

本教程演示如何使用 Azure Database for MySQL 灵活服务器。 若要使用其他数据库,请参阅 Azure Cosmos DBAzure SQLPostgreSQL 教程。

显示开发人员工具控制台窗口中 MySQL 结果的 Web 浏览器。

在本教程中,学习:

  • 将 Azure Database for MySQL 数据库链接到静态 Web 应用
  • 创建、读取、更新和删除数据

先决条件

若要完成本教程,需要拥有现有的 Azure Database for MySQL 数据库和静态 Web 应用。 此外,还需要安装 Visual Studio Code。

Resource Description
Azure Database for MySQL 灵活服务器 如果需要创建一个数据库,请按照创建 Azure Database for MySQL 灵活服务器指南中的步骤进行操作。 如果计划对 Web 应用使用连接字符串身份验证,请确保使用 MySQL 身份验证创建数据库。 如果以后想要使用托管标识,可以稍后更改此设置。
现有的静态 Web 应用 如果还没有,请按照 入门 指南中的步骤创建 No Framework 静态 Web 应用。
带有 MySQL Shell 扩展的 Visual Studio Code 如果尚未安装 Visual Studio Code,请按照指南安装 Visual Studio Code 以及 MySQL Shell 扩展。 或者,可以使用任何其他工具来查询 MySQL 数据库,例如 MySQL Workbench。

首先将数据库配置为使用 Azure Static Web Apps 数据库连接功能。

配置数据库连接

Azure Static Web Apps 必须对数据库具有网络访问权限,才能运行数据库连接。 此外,若要使用 Azure 数据库进行本地开发,需要将数据库配置为允许来自自己的 IP 地址的请求。

  1. Azure 门户中,转到 Azure Database for MySQL Server 灵活服务器。

  2. 在“设置”部分下,选择“网络”

  3. “防火墙规则 ”部分下,选择“ 添加当前客户端 IP 地址 ”按钮。 此步骤可确保将此数据库用于本地开发。

  4. 防火墙规则部分下,选中允许从 Azure 中的任何 Azure 服务公开访问此服务器复选框。 此步骤可确保已部署的静态 Web 应用资源可以访问数据库。

  5. 选择“保存”

获取用于本地开发的数据库连接字符串

若要使用 Azure 数据库进行本地开发,需要检索数据库的连接字符串。 如果打算将本地数据库用于开发目的,则可以跳过此步骤。

  1. Azure 门户 中访问 Azure Database for MySQL 灵活服务器。

  2. “设置” 部分下,选择“ 连接”。

  3. 从应用程序连接部分,选择 ADO.NET 连接字符串,并将其放入文本编辑器中备用。

  4. {your_password} 连接字符串中的占位符替换为密码。

  5. {your_database} 占位符替换为数据库名称 MyTestPersonDatabase。 你将在后续步骤中创建 MyTestPersonDatabase

  6. 删除连接字符串的 SslModeSslCa 部分,因为这些部分需要额外的步骤,旨在用于生产目的。

创建示例数据

创建一个示例表,并使用示例数据进行种子设定,以匹配本教程。 在这里,可以使用 Visual Studio Code,但可以使用 MySQL Workbench 或任何其他工具。

  1. 在 Visual Studio Code 中,使用 MySQL Shell 扩展创建与 Azure MySQL 灵活服务器的连接。

  2. 右键单击服务器并创建新数据库。 输入 MyTestPersonDatabase 作为数据库名称, 然后选择字符集为 utf8mb4,排序规则为 utf8mb4_0900_ai_ci

  3. 右键单击服务器,然后选择“ 刷新”。

  4. 右键单击 MyTestPersonDatabase 数据库并选择“ 新建查询”。 运行以下脚本以创建名为 MyTestPersonTable 的新表。

    CREATE TABLE MyTestPersonTable (
        Id INT AUTO_INCREMENT NOT NULL,
        Name VARCHAR(25) NULL,
        PRIMARY KEY (Id)
    );
    
  5. 运行以下脚本,将数据添加到 MyTestPersonTable 表中。

    INSERT INTO MyTestPersonTable (Name)
    VALUES ('Sunny');
    
    INSERT INTO MyTestPersonTable (Name)
    VALUES ('Dheeraj');
    
  6. 右键单击 MyTestPersonTable 表,然后选择 “选择前 1000 个” ,验证数据库中是否有数据。

配置静态 Web 应用

本教程的其余部分侧重于编辑静态 Web 应用的源代码,以在本地使用数据库连接。

重要

以下步骤假定你使用的是 在入门指南中创建的静态 Web 应用。 如果使用其他项目,请确保调整以下 git 命令以匹配分支名称。

  1. 切换到 main 分支。

    git checkout main
    
  2. 使用 git pull 将您本地的版本与 GitHub 上的版本同步。

    git pull origin main
    

创建数据库配置文件

接下来,创建静态 Web 应用用来与数据库进行交互的配置文件。

  1. 打开终端并创建一个新变量来保存连接字符串。 特定语法可能因所使用的 shell 类型而异。

    export DATABASE_CONNECTION_STRING='<YOUR_CONNECTION_STRING>'
    

    请确保将 <YOUR_CONNECTION_STRING> 替换为在文本编辑器中保留的连接字符串值。

  2. 使用 npm 安装或更新静态 Web 应用 CLI。 选择最适合你的情况的命令。

    若要安装,请使用 npm install

    npm install -g @azure/static-web-apps-cli
    

    若要更新,请使用 npm update

    npm update
    
  3. swa db init使用命令生成数据库配置文件。

    swa db init --database-type mysql
    

    init命令在 swa-db-connections 文件夹中创建 staticwebapp.database.config.json 文件。

  4. 将此示例粘贴到生成的文件 staticwebapp.database.config.json

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
  "data-source": {
    "database-type": "mysql",
    "options": {
      "set-session-context": false 
    },
    "connection-string": "@env('DATABASE_CONNECTION_STRING')"
  },
  "runtime": {
    "rest": {
      "enabled": true,
      "path": "/rest"
    },
    "graphql": {
      "allow-introspection": true,
      "enabled": true,
      "path": "/graphql"
    },
    "host": {
      "mode": "production",
      "cors": {
        "origins": ["http://localhost:4280"],
        "allow-credentials": false
      },
      "authentication": {
        "provider": "StaticWebApps"
      }
    }
  },
  "entities": {
    "Person": {
      "source": "MyTestPersonTable",
      "permissions": [
        {
          "actions": ["*"],
          "role": "anonymous"
        }
      ]
    }
  }
}

在继续执行下一步之前,请查看下表,其中介绍了配置文件的不同方面。 有关配置文件的完整文档,请参阅 数据 API Builder 文档

功能 / 特点 Explanation
数据库连接 在开发中,运行时从配置文件中的连接字符串的值读取连接字符串。 虽然可以直接在配置文件中指定连接字符串,但最佳做法是将连接字符串存储在本地环境变量中。 可以通过表示法引用配置文件 @env('DATABASE_CONNECTION_STRING') 中的环境变量值。 已部署站点的 Static Web Apps 将使用连接数据库时收集的信息覆盖连接字符串的值。
API 终结点 GraphQL 终结点按此配置文件中的配置通过/data-api/graphql提供,而 REST 终结点通过/data-api/rest提供。 可以配置 REST 和 GraphQL 路径,但 /data-api 前缀不可配置。
API 安全性 这些 runtime.host.cors 设置允许你定义允许的源,这些源可以向 API 发出请求。 在这种情况下,配置反映开发环境,并将 http://localhost:4280 位置列入允许列表。
实体模型 将 REST API 中通过路由公开的实体定义为 GraphQL 架构中的类型。 在这种情况下,Person是公开给终结点的名称,而entities.<NAME>.source则是指数据库架构和表映射。 请注意,API 终结点名称不需要与表名相同。
实体安全性 数组中列出的 entity.<NAME>.permissions 权限规则控制实体的授权设置。 使用角色保护实体的方法与使用角色保护路由的方法相同。

注释

部署站点时,配置文件中的connection-stringhost.modegraphql.allow-introspection属性将被覆盖。 使用在数据库连接到 Static Web Apps 资源时收集的身份验证详细信息覆盖连接字符串。 该 host.mode 属性设置为 production,并且 graphql.allow-introspection 设置为 false。 这些替代在开发和生产工作负荷的配置文件中提供一致性,同时确保启用了数据库连接的静态 Web 应用资源安全且生产就绪。

将静态 Web 应用配置为连接到数据库后,现在可以验证连接。

更新主页

body 文件中标记之间的标记替换为以下 HTML。

<h1>Static Web Apps Database Connections</h1>
<blockquote>
    Open the console in the browser developer tools to see the API responses.
</blockquote>
<div>
    <button id="list" onclick="list()">List</button>
    <button id="get" onclick="get()">Get</button>
    <button id="update" onclick="update()">Update</button>
    <button id="create" onclick="create()">Create</button>
    <button id="delete" onclick="del()">Delete</button>
</div>
<script>
    // add JavaScript here
</script>

在本地启动应用程序

现在您可以直接运行您的网站,并同时操作数据库中的数据。

  1. 使用数据库配置启动静态 Web 应用。

    swa start --data-api-location swa-db-connections
    

现在,CLI 已启动,可以通过 staticwebapp.database.config.json 文件中定义的终结点访问数据库。

终结点http://localhost:4280/data-api/rest/<ENTITY_NAME>接受GETPUTPOSTDELETE请求,以操作数据库中的数据。

终结点 http://localhost:4280/data-api/graphql 接受 GraphQL 查询和突变。

操作数据

以下与框架无关的命令演示如何对数据库执行完整的 CRUD 操作。

每个函数的输出将显示在浏览器的控制台窗口中。

通过按 CMD/CTRL + SHIFT + I 打开开发人员工具,然后选择 “控制台 ”选项卡。

列出所有项目

请在 script 标签之间的 index.html 中添加以下代码。

async function list() {
  const endpoint = '/data-api/rest/Person';
  const response = await fetch(endpoint);
  const data = await response.json();
  console.table(data.value);
}

在本示例中:

  • fetch API 的默认请求使用谓词 GET
  • 响应有效负载中的数据可以在value属性中找到。
async function list() {

  const query = `
      {
        people {
          items {
            Id
            Name
          }
        }
      }`;

  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ query: query })
  });
  const result = await response.json();
  console.table(result.data.people.items);
}

在本示例中:

  • GraphQL 查询从数据库中选择 IdName 字段。
  • 传递给服务器的请求需要一个有效负载, query 其中属性包含查询定义。
  • 响应有效负载中的数据可以在 data.people.items 属性中找到。

刷新页面,然后选择 “列表 ”按钮。

浏览器的控制台窗口现在显示一个表,其中列出了数据库中的所有记录。

ID Name
1 Sunny
2 Dheeraj

下面是浏览器中应显示的内容的屏幕截图。

显示开发人员工具控制台窗口中数据库选择结果的 Web 浏览器。

按 ID 获取

script标记之间添加以下代码。

async function get() {
  const id = 1;
  const endpoint = `/data-api/rest/Person/Id`;
  const response = await fetch(`${endpoint}/${id}`);
  const result = await response.json();
  console.table(result.value);
}

在本示例中:

  • 终结点后缀为 /person/Id.
  • ID 值将追加到终结点位置的末尾。
  • value属性中可以找到响应有效负载中的数据。
async function get() {

  const id = 1;

  const gql = `
    query getById($id: Int!) {
      person_by_pk(Id: $id) {
        Id
        Name
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
    },
  };

  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query),
  });
  const result = await response.json();
  console.table(result.data.person_by_pk);
}

在本示例中:

  • GraphQL 查询从数据库中选择 IdName 字段。
  • 传递给服务器的请求需要一个有效负载, query 其中属性包含查询定义。
  • data.person_by_pk 属性中找到响应有效负载中的数据。

刷新页面并选择“ 获取 ”按钮。

浏览器的控制台窗口现在显示一个表,其中列出了从数据库请求的单条记录。

ID Name
1 Sunny

Update

script标签之间,将以下代码添加到index.html中。

静态 Web 应用支持两种谓词:PUTPATCH。 请求 PUT 更新整个记录,同时 PATCH 执行部分更新。

async function update() {

  const id = 1;
  const data = {
    Name: "Molly"
  };

  const endpoint = '/data-api/rest/Person/Id';
  const response = await fetch(`${endpoint}/${id}`, {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(data)
  });
  const result = await response.json();
  console.table(result.value);
}

在本示例中:

  • 终结点后缀为 /person/Id/.
  • ID 值将追加到终结点位置的末尾。
  • REST 谓词是 PUT 以更新数据库记录。
  • 响应有效负载中的数据位于属性value中。
async function update() {

  const id = 1;
  const data = {
    Name: "Molly"
  };

  const gql = `
    mutation update($id: Int!, $item: UpdatePersonInput!) {
      updatePerson(Id: $id, item: $item) {
        Id
        Name
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
      item: data
    } 
  };

  const endpoint = "/data-api/graphql";
  const res = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const result = await res.json();
  console.table(result.data.updatePerson);
}

在本示例中:

  • GraphQL 查询从数据库中选择 IdName 字段。
  • query 对象在 query 属性中保存 GraphQL 查询。
  • GraphQL 函数的参数值通过 query.variables 属性传入。
  • 传递给服务器的请求需要一个有效负载, query 其中属性包含查询定义。
  • 响应有效负载中的数据可在 data.updatePerson 属性中找到。

刷新页面,然后选择 “更新 ”按钮。

浏览器的控制台窗口现在显示一个表,其中显示了更新的数据。

ID Name
1 莫莉

创建

script 标签内的 index.html 中插入以下代码。

async function create() {

  const data = {
    Name: "Pedro"
  };

  const endpoint = `/data-api/rest/Person/`;
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(data)
  });
  const result = await response.json();
  console.table(result.value);
}

在本示例中:

  • 终结点后缀为 /person/.
  • REST 动词是 POST 添加数据库记录。
  • 响应有效负载中的数据位于 value 属性中。
async function create() {

  const data = {
    Name: "Pedro"
  };

  const gql = `
    mutation create($item: CreatePersonInput!) {
      createPerson(item: $item) {
        Id
        Name
      }
    }`;

  const query = {
    query: gql,
    variables: {
      item: data
    } 
  };

  const endpoint = "/data-api/graphql";
  const result = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const response = await result.json();
  console.table(response.data.createPerson);
}

在本示例中:

  • GraphQL 查询从数据库中选择 IdName 字段。
  • query 对象在 query 属性中保存 GraphQL 查询。
  • GraphQL 函数的参数值通过 query.variables 属性传入。
  • 传递给服务器的请求需要一个有效负载, query 其中属性包含查询定义。
  • data.updatePerson 属性中找到响应有效负载中的数据。

刷新页面并选择“ 创建 ”按钮。

浏览器的控制台窗口现在显示一个表,其中显示了数据库中的新记录。

ID Name
3 佩德罗

删除

index.htmlscript标签之间添加以下代码。

async function del() {
  const id = 3;
  const endpoint = '/data-api/rest/Person/Id';
  const response = await fetch(`${endpoint}/${id}`, {
    method: "DELETE"
  });
  if(response.ok) {
    console.log(`Record deleted: ${ id }`)
  } else {
    console.log(response);
  }
}

在本示例中:

  • 终结点后缀为 /person/Id/.
  • ID 值将追加到终结点位置的末尾。
  • REST 动词是 DELETE 来删除数据库记录。
  • 如果删除成功,则响应有效负载 ok 属性为 true
async function del() {

  const id = 3;

  const gql = `
    mutation del($id: Int!) {
      deletePerson(Id: $id) {
        Id
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id
    }
  };

  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const result = await response.json();
  console.log(`Record deleted: ${ result.data.deletePerson.Id }`);
}

在本示例中:

  • GraphQL 查询从数据库中选择 Id 字段。
  • query 对象在 query 属性中保存 GraphQL 查询。
  • GraphQL 函数的参数值通过 query.variables 属性传入。
  • 传递给服务器的请求需要一个有效负载, query 其中属性包含查询定义。
  • 响应有效负载中的数据位于data.deletePerson 属性中。

刷新页面,然后选择“ 删除 ”按钮。

浏览器的控制台窗口现在显示一个表,其中显示了来自删除请求的响应。

已删除记录:3

你已经在本地开发了站点,现在可以将其部署到 Azure。

部署您的站点

若要将此站点部署到生产环境,只需提交配置文件并将更改推送到服务器。

  1. 添加要跟踪的文件更改。

    git add .
    
  2. 提交配置更改。

    git commit -am "Add database configuration"
    
  3. 将更改推送到服务器。

    git push origin main
    

将数据库连接到静态 Web 应用

使用以下步骤在站点的静态 Web 应用实例与数据库之间创建连接。

  1. 在 Azure 门户中打开静态 Web 应用。

  2. “设置” 部分中,选择 “数据库连接”。

  3. “生产 ”部分下,选择 “链接现有数据库 ”链接。

  4. “链接现有数据库 ”窗口中,输入以下值:

    资产 价值
    数据库类型 从下拉列表中选择数据库类型。
    Subscription 从下拉列表中选择 Azure 订阅。
    资源名称 选择具有所需数据库的数据库服务器名称。
    数据库名称 选择要链接到静态 Web 应用的数据库的名称。
    身份验证类型 选择 连接字符串,并输入 MySQL 用户名和密码。
  5. 选择“确定”

验证数据库是否已连接到静态 Web 应用资源

将数据库连接到静态 Web 应用并完成站点生成后,请使用以下步骤验证数据库连接。

  1. 在 Azure 门户中打开静态 Web 应用。

  2. “概要” 部分中,选择静态 Web 应用资源的 URL 以导航到静态 Web 应用。

  3. 选择 “列表 ”按钮可列出所有项。

    输出应类似于此屏幕截图中显示的内容。

    在开发者工具控制台窗口中显示数据库记录列表结果的 Web 浏览器。

清理资源

如果要删除在本教程中创建的资源,则需要取消链接数据库并删除示例数据。

  1. 取消链接数据库:在 Azure 门户中打开静态 Web 应用。 在 “设置” 部分下,选择 “数据库连接”。 在链接的数据库旁边,选择“ 查看详细信息”。 在 “数据库连接详细信息 ”窗口中,选择“ 取消链接 ”按钮。

  2. 删除示例数据:在数据库中,删除名为 MyTestPersonTable的表。

后续步骤