教學:在 Azure 靜態網頁應用中新增 MySQL 資料庫連線(預覽)

在這個教學中,你將學習如何將 Azure Database for MySQL Flexible Server 資料庫連接到你的靜態網頁應用程式。 設定完成後,你可以向內建 /data-api 端點發送 REST 或 GraphQL 請求,無需撰寫後端程式碼即可操作資料。

為了簡化起見,本教學示範如何使用 Azure 資料庫進行本地開發,但你也可以使用本地資料庫伺服器來滿足本地開發需求。

備註

這個教學示範如何使用 Azure Database for MySQL Flexible Server。 如果你想使用其他資料庫,請參考 Azure Cosmos DBAzure SQLPostgreSQL 的教學。

網頁瀏覽器在開發者工具主控台視窗中顯示 MySQL 的結果。

在本教學課程中,您將了解:

  • 將 Azure Database for MySQL 資料庫連結到你的靜態網頁應用程式
  • 建立、讀取、更新及刪除資料

先決條件

要完成這個教學,你需要有一個現有的 Azure Database for MySQL 資料庫和靜態網頁應用程式。 此外,你需要安裝 Visual Studio Code。

Resource Description
適用於 MySQL 的 Azure 資料庫彈性伺服器 如果你需要建立資料庫,請依照 MySQL 靈活伺服器建立 Azure 資料庫 指南的步驟操作。 如果你打算為網頁應用程式使用連線字串認證,請確保你建立資料庫時有 MySQL 認證。 如果你之後想用管理身份,可以之後更改這個設定。
現有的靜態網頁應用程式 如果你還沒有,請依照 入門 指南的步驟建立 一個 No Framework 靜態網頁應用程式。
Visual Studio Code,搭配 MySQL Shell 擴充功能 如果你還沒安裝 Visual Studio Code,請依照教學安裝 Visual Studio Code,並搭配 MySQL Shell 擴充功能。 或者,你也可以使用其他工具查詢你的 MySQL 資料庫,例如 MySQL Workbench。

首先,先設定你的資料庫以配合 Azure 靜態網路應用的資料庫連線功能。

設定資料庫連接

Azure 靜態 Web Apps 必須有網路存取你的資料庫,資料庫連線才能正常運作。 此外,若要使用 Azure 資料庫進行本地開發,你需要設定資料庫允許來自你自己 IP 位址的請求。

  1. 請在 Azure 入口網站中進入你的 MySQL Server Flexible Server 的 Azure 資料庫。

  2. 在 [設定] 區段中,選取 [網路]

  3. 防火牆規則 區塊中,選擇 「新增您目前的用戶端 IP 位址 」按鈕。 此步驟確保您能將此資料庫用於本地開發。

  4. 防火牆規則 區塊中,選擇 「允許從 Azure 內任何 Azure 服務對此伺服器的公開存取 」勾選框。 此步驟確保你部署的靜態 Web Apps 資源能存取你的資料庫。

  5. 選取 [儲存]。

取得資料庫連線字串用於本地開發

要使用 Azure 資料庫進行本地開發,你需要取得資料庫的連線字串。 如果你打算用本地資料庫來開發,可以跳過這個步驟。

  1. 請在 Azure 入口網站中進入你的 MySQL Server Flexible Server 的 Azure 資料庫。

  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 Flexible Server。

  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 名」以確認你的資料庫中有資料。

設定靜態網頁應用程式

接下來的教學重點是如何編輯你靜態網頁應用程式的原始碼,讓它能在本地利用資料庫連線。

這很重要

以下步驟假設你使用的是在入門指南中所建立的靜態網頁應用程式。 如果你用的是不同的專案,請確保調整以下 git 指令,使其與你的分支名稱相符。

  1. 轉到 main 分行。

    git checkout main
    
  2. 用 .() git pull同步你的本地版本和 GitHub 上的版本。

    git pull origin main
    

建立資料庫設定檔

接著,建立你的靜態網頁應用程式用來與資料庫介面的設定檔。

  1. 打開你的終端機,建立一個新的變數來存放你的連線字串。 具體語法可能會依你使用的 shell 類型而有所不同。

    export DATABASE_CONNECTION_STRING='<YOUR_CONNECTION_STRING>'
    

    記得用你在文字編輯器中預留的 connections 字串值來替換 <YOUR_CONNECTION_STRING>

  2. 使用 npm 安裝或更新靜態網頁應用程式的 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"
        }
      ]
    }
  }
}

在進入下一步之前,請先參考以下表格,說明設定檔的不同面向。 關於設定檔的完整文件,請參閱 Data API Builder 文件

特徵 / 功能 Explanation
資料庫連接 在開發過程中,執行時會從設定檔中連接字串的值讀取連接字串。 雖然你可以直接在設定檔中指定連接字串,但最佳做法是將連接字串存放在本地環境變數中。 你可以透過 @env('DATABASE_CONNECTION_STRING') 符號在設定檔中引用環境變數的值。 連線字串的值會在部署站點時被靜態網頁應用覆蓋,這包括你在連接資料庫時收集的資訊。
API 端點 REST 端點可透過 /data-api/rest 此設定檔存取,而 GraphQL 端點則可依 /data-api/graphql 照此設定檔的設定方式使用。 你可以設定 REST 和 GraphQL 路徑,但 /data-api 前綴無法設定。
API 安全性 這些設定允許你定義可以向 API 發出請求的來源。 在此情況下,配置反映開發環境並將 http://localhost:4280 地點列入允許清單。
實體模型 定義透過 REST API 路由或 GraphQL 架構中的類型所公開的實體。 在此情況下,名稱 Person 是暴露給端點的名稱,而 entities.<NAME>.source 則是資料庫架構與資料表映射。 注意 API 端點名稱不必與資料表名稱相同。
實體安全 陣列中 entity.<NAME>.permissions 列出的權限規則控制實體的授權設定。 你可以用角色來保護實體,就像用 角色保護路由一樣。

備註

部署網站時,設定檔的 connection-stringhost.modegraphql.allow-introspection 屬性都會被覆寫。 你的連線字串會被你連接資料庫到靜態網頁應用程式資源時收集的認證細節覆蓋。 host.mode屬性設為 production,且 graphql.allow-introspection 設為 false。 這些覆寫確保你的設定檔在開發與生產工作負載中保持一致性,同時確保啟用資料庫連線的靜態網頁應用資源安全且準備好生產環境。

當靜態網頁應用程式設定為連接資料庫後,你現在可以驗證連線。

更新首頁

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. 用資料庫設定啟動靜態網頁應用程式。

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

現在 CLI 已經啟動,你可以透過staticwebapp.database.config.json檔案內定義的端點存取資料庫。

http://localhost:4280/data-api/rest/<ENTITY_NAME>端點接受 GETPUT、 以及 POSTDELETE操作資料庫資料的請求。

http://localhost:4280/data-api/graphql 點接受 GraphQL 查詢與變異。

操作資料

以下這些框架無關指令示範如何在資料庫上執行完整的 CRUD 操作。

每個函式的輸出會顯示在瀏覽器的主控台視窗中。

CMD/CTRL + SHIFT + I 開啟開發者工具,選擇 Console 標籤。

列出所有項目

script的標籤間加上以下代碼。

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

在此範例中:

  • API 的預設請求 fetch 使用動詞 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 名稱
1 Sunny
2 迪拉吉

這裡有一張瀏覽器中應該長什麼樣子的截圖。

網頁瀏覽器在開發者工具主控台視窗中顯示資料庫選取的結果。

通過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 查詢會從資料庫中選取 Id 欄位和 Name 欄位。
  • 傳送給伺服器的請求需要一個有效載荷,該屬性包含 query 查詢定義。
  • 回應有效載荷中的資料可在 data.person_by_pk 屬性中找到。

重新整理頁面並選擇 「取得 」按鈕。

瀏覽器的主控台視窗現在顯示一個表格,列出從資料庫中請求的單一紀錄。

ID 名稱
1 Sunny

Update

script的標籤間加上以下代碼。

靜態網頁應用程式支援 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 名稱
1 莫莉

Create

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 查詢會從資料庫中選擇IdName 欄位。
  • 物件在 query 屬性 query 中保留 GraphQL 查詢。
  • GraphQL 函式的參數值會透過 屬性 query.variables 傳遞。
  • 傳送給伺服器的請求需要一個有效載荷,該屬性包含 query 查詢定義。
  • 回應有效載荷中的資料可在 data.updatePerson 屬性中找到。

重新整理頁面並選擇 建立 按鈕。

瀏覽器的主控台視窗現在顯示一個顯示資料庫中新紀錄的表格。

ID 名稱
3 佩德羅

刪除

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。

部署您的網站

要將這個網站部署到生產環境,你只需要提交設定檔並將變更推送到伺服器即可。

  1. 新增檔案變更以追蹤。

    git add .
    
  2. 提交設定變更。

    git commit -am "Add database configuration"
    
  3. 把你的變更推送到伺服器。

    git push origin main
    

將資料庫連接到你的靜態網頁應用程式

請依照以下步驟建立靜態網頁應用實例與資料庫之間的連結。

  1. 在 Azure 入口網站中開啟靜態您的 Web 應用程式

  2. 設定 區塊,選擇 資料庫連線

  3. 生產 區塊中,選擇 「連結現有資料庫 連結」。

  4. Link 現有資料庫 視窗中,輸入以下數值:

    房產 價值觀
    資料庫類型 從下拉選單中選擇你的資料庫類型。
    Subscription 從下拉選單中選擇您的 Azure 訂閱。
    資源名稱 選擇包含你想要資料庫的資料庫伺服器名稱。
    資料庫名稱 選擇你想連結到靜態網頁應用程式的資料庫名稱。
    驗證類型 選擇 連線字串,輸入 MySQL 的使用者名稱和密碼。
  5. 請選擇 [確定]

確認你的資料庫是否連接到靜態 Web Apps 資源

當你將資料庫連接到靜態網頁應用程式並完成建置後,請依照以下步驟驗證資料庫連線。

  1. 在 Azure 入口網站中開啟靜態您的 Web 應用程式

  2. Essentials 區塊,選擇你的靜態網頁應用程式 資源網址, 以導覽到你的靜態網頁應用程式。

  3. 選擇 清單 按鈕以列出所有項目。

    輸出應該會和這張截圖中顯示的差不多。

    網頁瀏覽器顯示在開發者工具主控台視窗中列出資料庫記錄的結果。

清理資源

如果你想移除本教學中建立的資源,你需要解除資料庫連結並移除範例資料。

  1. 解除資料庫連結:在 Azure 入口網站開啟你的靜態網頁應用程式。 在 設定 區塊中,選擇 資料庫連線。 在連結資料庫旁,選擇 查看詳情。 在 資料庫連線詳情 視窗中,選擇 「解除連結 」按鈕。

  2. 移除範例資料:在您的資料庫中刪除名為 MyTestPersonTable的表格。

後續步驟