你当前正在访问 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 DB、Azure SQL 或 PostgreSQL 教程。
在本教程中,学习:
- 将 Azure Database for MySQL 数据库链接到静态 Web 应用
- 创建、读取、更新和删除数据
先决条件
若要完成本教程,需要已有 Azure Database for MySQL 数据库和静态 Web 应用。 此外,还需要安装 Azure Data Studio。
资源 | 说明 |
---|---|
Azure Database for MySQL 灵活服务器 | 如需创建数据库,请按照创建 Azure Database for MySQL 灵活服务器指南中的步骤操作。 如果计划对 Web 应用使用连接字符串身份验证,请确保使用 MySQL 身份验证创建数据库。 如果以后想要使用托管标识,可以之后更改此设置。 |
现有的静态 Web 应用 | 如果还没有,请按照入门指南中的步骤创建无框架静态 Web 应用。 |
Azure Data Studio(带 MySQL 扩展) | 如果尚未安装 Azure Data Studio,请遵循关于安装 Azure Data Studio(带 MySQL 扩展)的指南。 或者,可以使用任何其他工具来查询 MySQL 数据库,例如 MySQL Workbench。 |
首先将数据库配置为使用 Azure Static Web Apps 数据库连接功能。
配置数据库连接
Azure Static Web Apps 必须对数据库具有网络访问权限,数据库连接才能正常工作。 此外,若要使用 Azure 数据库进行本地开发,需要配置数据库,以允许来自你自己的 IP 地址的请求。
在 Azure 门户中,转到 Azure Database for MySQL Server 灵活服务器。
在“设置”部分下,选择“网络”。
在“防火墙规则”部分下,选择“添加当前客户端 IP 地址”按钮。 此步骤可确保可以将此数据库用于本地开发。
在“防火墙规则”部分下,选中“允许从 Azure 中的任何 Azure 服务公开访问此服务器”复选框。 此步骤可确保部署的 Static Web Apps 资源可以访问数据库。
选择“保存” 。
获取用于本地开发的数据库连接字符串
若要使用 Azure 数据库进行本地开发,需要检索数据库的连接字符串。 如果计划使用本地数据库进行开发,则可跳过此步骤。
在 Azure 门户中,转到 Azure Database for MySQL Server 灵活服务器。
在“设置”部分下,选择“连接”。
在“从应用连接”部分中,选择 ADO.NET 连接字符串,并将其放在文本编辑器中。
将连接字符串中的
{your_password}
占位符替换为密码。将
{your_database}
占位符替换为数据库名称MyTestPersonDatabase
。 你将在后续步骤中创建MyTestPersonDatabase
。删除连接字符串的 SslMode 和 SslCa 部分,因为这些部分需要额外的步骤并用于生产目的。
创建示例数据
创建一个示例表,并使用示例数据为其设定种子,以便与本教程相符。 在这里,可以使用 Azure Data Studio,但也可以使用 MySQL Workbench 或任何其他工具。
在 Azure Data Studio 中,创建与 Azure MySQL 灵活服务器的连接。
右键单击服务器,并创建新数据库。 输入
MyTestPersonDatabase
作为数据库名称,然后选择utf8mb4
字符集,选择utf8mb4_0900_ai_ci
排序规则。右键单击服务器并选择“刷新”。
右键单击
MyTestPersonDatabase
数据库并选择“新建查询”。 运行以下脚本,创建名为MyTestPersonTable
的新表。CREATE TABLE MyTestPersonTable ( Id INT AUTO_INCREMENT NOT NULL, Name VARCHAR(25) NULL, PRIMARY KEY (Id) );
运行以下脚本,将数据添加到
MyTestPersonTable
表中。INSERT INTO MyTestPersonTable (Name) VALUES ('Sunny'); INSERT INTO MyTestPersonTable (Name) VALUES ('Dheeraj');
右键单击
MyTestPersonTable
表,然后选择“选择前 1000 个”,验证数据库中是否有数据。
配置静态 Web 应用
本教程的其余部分重点介绍如何编辑静态 Web 应用的源代码,以便在本地使用数据库连接。
重要
以下步骤假定你使用的是在入门指南中创建的静态 Web 应用。 如果使用的是其他项目,请确保调整以下 git 命令以匹配分支名称。
切换到
main
分支。git checkout main
使用
git pull
将本地版本与 GitHub 上的内容同步。git pull origin main
创建数据库配置文件
接下来,创建供静态 Web 应用用来与数据库进行交互的配置文件。
打开终端并创建一个新变量来保存连接字符串。 具体语法可能因所使用的 shell 类型而异。
export DATABASE_CONNECTION_STRING='<YOUR_CONNECTION_STRING>'
请确保将
<YOUR_CONNECTION_STRING>
替换为在文本编辑器中保留的连接字符串值。使用 npm 安装或更新 Static Web Apps CLI。 选择最适合你的情况的命令。
若要安装,请使用
npm install
。npm install -g @azure/static-web-apps-cli
若要更新,请使用
npm update
。npm update
使用
swa db init
命令生成数据库配置文件。swa db init --database-type mysql
init
命令在 swa-db-connections 文件夹中创建 staticwebapp.database.config.json 文件。将此示例粘贴到生成的 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 生成器文档。
功能 | 说明 |
---|---|
数据库连接 | 在开发过程中,运行时从配置文件中的连接字符串值读取连接字符串。 虽然可以直接在配置文件中指定连接字符串,但最佳做法是将连接字符串存储在本地环境变量中。 可以通过 @env('DATABASE_CONNECTION_STRING') 表示法引用配置文件中的环境变量值。 已部署站点的 Static Web Apps 将使用连接数据库时收集的信息覆盖连接字符串的值。 |
API 终结点 | REST 终结点通过 /data-api/rest 可用,而 GraphQL 终结点通过 /data-api/graphql 可用,如此配置文件中所配置。 可以配置 REST 和 GraphQL 路径,但 /data-api 前缀不可配置。 |
API 安全性 | 利用 runtime.host.cors 设置,可以定义能够向 API 发出请求的允许的源。 在这种情况下,配置反映开发环境,并将 http://localhost:4280 位置列入允许列表。 |
实体模型 | 将 REST API 中通过路由公开的实体定义为 GraphQL 架构中的类型。 在这种情况下,名称 Person 是公开给终结点的名称,而 entities.<NAME>.source 名称是数据库架构和表映射。 请注意,API 终结点名称不需要与表名称相同。 |
实体安全性 | entity.<NAME>.permissions 数组中列出的权限规则控制实体的授权设置。 使用角色保护实体的方法与使用角色保护路由的方法相同。 |
注意
部署站点时,覆盖配置文件的 connection-string
、host.mode
和 graphql.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>
在本地启动应用程序
现在,你可以直接运行网站并操作数据库中的数据。
使用数据库配置启动静态 Web 应用。
swa start ./src --data-api-location swa-db-connections
CLI 现已启动,接下来可通过 staticwebapp.database.config.json 文件中定义的终结点访问数据库。
http://localhost:4280/data-api/rest/<ENTITY_NAME>
终结点接受 GET
、PUT
、POST
和 DELETE
请求以在数据库中操作数据。
http://localhost:4280/data-api/graphql
终结点接受 GraphQL 查询和变更。
操作数据
以下不局限于特定框架的命令演示了如何对数据库执行完整的 CRUD 操作。
每个函数的输出将显示在浏览器的控制台窗口中。
按 CMD/CTRL + SHIFT + I 打开开发人员工具,然后选择“控制台”选项卡。
列出所有项
在 index.html 中的 script
标记之间添加以下代码。
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 查询从数据库中选择
Id
和Name
字段。 - 传递给服务器的请求需要一个有效负载(其中的
query
属性包含查询定义)。 - 响应有效负载中的数据可在
data.people.items
属性中找到。
刷新页面,然后选择“列表”按钮。
浏览器的控制台窗口现在显示了一个表,其中列出了数据库中的所有记录。
ID | 名称 |
---|---|
1 | 晴 |
2 | Dheeraj |
下面是浏览器外观的屏幕截图。
按 ID 获取
在 index.html 中的 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 查询从数据库中选择
Id
和Name
字段。 - 传递给服务器的请求需要一个有效负载(其中的
query
属性包含查询定义)。 - 响应有效负载中的数据可在
data.person_by_pk
属性中找到。
刷新页面,然后选择“获取”按钮。
浏览器的控制台窗口现在显示了一个表,其中列出了从数据库请求的单条记录。
ID | 名称 |
---|---|
1 | 晴 |
更新
在 index.html 中的 script
标记之间添加以下代码。
Static Web Apps支持 PUT
和 PATCH
谓词。 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 查询从数据库中选择
Id
和Name
字段。 query
对象在query
属性中保存 GraphQL 查询。- GraphQL 函数的参数值通过
query.variables
属性传入。 - 传递给服务器的请求需要一个有效负载(其中的
query
属性包含查询定义)。 - 响应有效负载中的数据可在
data.updatePerson
属性中找到。
刷新页面并选择“更新”按钮。
浏览器的控制台窗口现在显示了一个表,其中显示了更新的数据。
ID | 名称 |
---|---|
1 | Molly |
创建
在 index.html 中的 script
标记之间添加以下代码。
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 查询从数据库中选择
Id
和Name
字段。 query
对象在query
属性中保存 GraphQL 查询。- GraphQL 函数的参数值通过
query.variables
属性传入。 - 传递给服务器的请求需要一个有效负载(其中的
query
属性包含查询定义)。 - 响应有效负载中的数据可在
data.updatePerson
属性中找到。
刷新页面并选择“创建”按钮。
浏览器的控制台窗口现在显示了一个表,其中显示了数据库中的新记录。
ID | 名称 |
---|---|
3 | Pedro |
删除
在 index.html 中的 script
标记之间添加以下代码。
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。
部署站点
若要将此站点部署到生产环境,只需提交配置文件并将更改推送到服务器。
添加要跟踪的文件更改。
git add .
提交配置更改。
git commit -am "Add database configuration"
将更改推送到服务器。
git push origin main
将数据库连接到静态 Web 应用
使用以下步骤在站点的 Static Web Apps 实例与数据库之间创建连接。
在 Azure 门户中打开静态 Web 应用。
在“设置”部分中,选择“数据库连接”。
在“生产”部分下,选择“链接现有数据库”链接。
在“链接现有数据库”窗口中,输入以下值:
属性 值 数据库类型 从下拉列表中选择你的数据库类型。 订阅 从下拉列表中选择你的 Azure 订阅。 资源名称 选择具有所需数据库的数据库服务器名称。 数据库名称 选择要链接到静态 Web 应用的数据库的名称。 身份验证类型 选择“连接字符串”,然后输入 MySQL 用户名和密码。 选择“确定” 。
验证数据库是否已连接到 Static Web Apps 资源
将数据库连接到静态 Web 应用并完成站点的构建后,请使用以下步骤验证数据库连接。
在 Azure 门户中打开静态 Web 应用。
在“概要”部分中,选择 Static Web Apps 资源的 URL 以导航到静态 Web 应用。
选择“列出”按钮,列出所有项。
输出应类似于此屏幕截图中显示的内容。
清理资源
如果要移除本教程期间创建的资源,需要取消数据库链接并移除示例数据。
取消数据库链接:在 Azure 门户中打开你的静态 Web 应用。 在“设置”部分下,选择“数据库连接”。 在链接数据库旁边,选择“查看详细信息”。 在“数据库连接详细信息”窗口中,选择“取消链接”按钮。
移除示例数据:在数据库中,删除名为
MyTestPersonTable
的表。