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

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

本教程介绍如何将 Azure Cosmos DB for NoSQL 数据库连接到静态 Web 应用。 配置后,可以向内置的 /data-api 终结点发出 GraphQL 请求以操作数据,而无需编写后端代码。

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

注意

本教程演示如何使用 Azure Cosmos DB for NoSQL。 若要使用其他数据库,请参阅 Azure SQLMySQLPostgreSQL 教程。

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

在本教程中,学习:

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

先决条件

若要完成本教程,需要已有 Azure Cosmos DB for NoSQL 数据库和静态 Web 应用。

资源 说明
Azure Cosmos DB for NoSQL 数据库 如果还没有,请按照创建 Azure Cosmos DB 数据库指南中的步骤操作。
现有的静态 Web 应用 如果还没有,请按照入门指南中的步骤创建无框架静态 Web 应用。

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

配置数据库连接

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

  1. 转到 Azure 门户中的 Azure Cosmos DB for NoSQL 帐户。

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

  3. 在“公共访问”部分下,选择“所有网络”。 通过此操作,可使用云数据库进行本地开发,部署的 Static Web Apps 资源可以访问数据库,并且你可通过门户查询数据库。

  4. 选择“保存” 。

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

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

  1. 转到 Azure 门户中的 Azure Cosmos DB for NoSQL 帐户。

  2. 在“设置”部分下,选择“密钥”。

  3. 在“主连接字符串”框中,复制连接字符串并将其放在文本编辑器中。

创建示例数据

创建一个示例表,并使用示例数据为其设定种子,以便与本教程相符。

  1. 在左侧导航窗口中,选择“数据资源管理器”。

  2. 选择“新建容器”。 输入数据库 ID 作为 Create new,然后输入 MyTestPersonDatabase 作为值。

  3. 输入 MyTestPersonContainer 的容器 ID。

  4. 输入分区键 id(此值的前缀为 /)。

  5. 选择“确定” 。

  6. 选择 MyTestPersonContainer 容器。

  7. 选择其“项”。

  8. 选择“新建项”并输入以下值:

    {
        "id": "1",
        "Name": "Sunny"
    }
    

配置静态 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 安装或更新 Static Web Apps CLI。 选择最适合你的情况的命令。

    若要安装,请使用 npm install

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

    若要更新,请使用 npm update

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

    swa db init --database-type cosmosdb_nosql --cosmosdb_nosql-database MyTestPersonDatabase
    

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

  4. 将此示例架构粘贴到生成的 staticwebapp.database.schema.gql 文件中。

    由于 Cosmos DB for NoSQL 是一种不局限于特定架构的数据库,因此 Azure Static Web Apps 数据库连接无法提取数据库的架构。 利用 staticwebapp.database.schema.gql 文件,可以为 Static Web Apps 指定 Cosmos DB for NoSQL 数据库的架构。

    type Person @model {
      id: ID
      Name: String
    }
    
  5. 将此示例配置粘贴到生成的 staticwebapp.database.config.json 文件中。 请注意,Cosmos DB for NoSQL 在 data-source 对象中具有更多选项,用于指示 Cosmos DB 数据库以及供数据库连接了解数据库架构所需的架构文件。

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
  "data-source": {
    "database-type": "cosmosdb_nosql",
    "options": {
      "database": "MyTestPersonDatabase",
      "schema": "staticwebapp.database.schema.gql"
    },
    "connection-string": "@env('DATABASE_CONNECTION_STRING')"
  },
  "runtime": {
    "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": "MyTestPersonContainer",
      "permissions": [
        {
          "actions": ["*"],
          "role": "anonymous"
        }
      ]
    }
  }
}

在继续执行下一步之前,请查看下表,其中说明了配置文件的各个方面。 有关配置文件和功能(例如项目级安全关系和策略)的完整文档,请参阅数据 API 生成器文档

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

注意

部署站点时,覆盖配置文件的 connection-stringhost.modegraphql.allow-introspection 属性。 使用在数据库连接到 Static Web Apps 资源时收集的身份验证详细信息覆盖连接字符串。 将 host.mode 属性设置为 production,将 graphql.allow-introspection 设置为 false。 这些替代值可让配置文件在整个开发和生产工作负载中保持一致,同时确保启用了数据库连接的 Static Web Apps 资源安安全无虞并可用于生产环境。

配置静态 Web 应用以连接到数据库后,接下来就可以验证连接了。

更新主页

将 index.html 文件中 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>

在本地启动应用程序

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

重要

为了提高通过 Static Web Apps CLI 进行部署的安全性,我们引入了一项中断性变更,需要你在 2025 年 1 月 15 日前升级到 Static Web Apps CLI 的最新版本 (2.0.2)。

  1. 使用 npm 安装或更新 Static Web Apps CLI。 选择最适合你的情况的命令。

    若要安装,请使用 npm install

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

    若要更新,请使用 npm update

    npm update
    
  2. 使用数据库配置启动静态 Web 应用。

    swa start ./src --data-api-location swa-db-connections
    

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

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

操作数据

以下不局限于特定框架的命令演示了如何对数据库执行完整的 CRUD 操作。

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

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

列出所有项

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

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 名称
1
2 Dheeraj

下面是浏览器外观的屏幕截图。

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

按 ID 获取

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

async function get() {

  const id = '1';

  const gql = `
    query getById($id: ID!) {
      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 名称
1

更新

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

async function update() {

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

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

  const query = {
    query: gql,
    variables: {
      id: id,
      _partitionKeyValue: 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 名称
1 Molly

创建

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

async function create() {

  const data = {
    id: "3",
    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 名称
3 Pedro

删除

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

async function del() {

  const id = '3';

  const gql = `
    mutation del($id: ID!, $_partitionKeyValue: String!) {
      deletePerson(id: $id, _partitionKeyValue: $_partitionKeyValue) {
        id
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
    _partitionKeyValue: 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: ${ JSON.stringify(result.data) }`);
}

在此示例中:

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

刷新页面并选择“删除”按钮。

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

已删除记录:2

现在你已在本地处理了站点,接下来可将其部署到 Azure。

部署站点

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

  1. 提交配置更改。

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

    git push origin main
    
  3. 等待 Web 应用生成。

  4. 转到浏览器中的静态 Web 应用。

  5. 选择“列出”按钮,列出所有项。

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

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

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

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

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

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

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

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

    属性
    数据库类型 从下拉列表中选择你的数据库类型。
    订阅 从下拉列表中选择你的 Azure 订阅。
    数据库名称 选择要链接到静态 Web 应用的数据库的名称。
    身份验证类型 选择“连接字符串”。
  5. 选择“确定” 。

验证数据库是否已连接到 Static Web Apps 资源

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

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

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

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

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

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

清理资源

如果要移除本教程期间创建的资源,需要取消数据库链接并移除示例数据。

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

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

后续步骤