共用方式為


教學課程:在 Azure Static Web Apps 中新增 PostgreSQL 資料庫連線 (預覽版)

在本教學課程中,您會了解如何將 Azure Database for PostgreSQL 單一伺服器或彈性伺服器資料庫連線到您的靜態 Web 應用程式。 完成設定後,您可以對內建的 /data-api 端點提出 REST 或 GraphQL 要求,以便在不必撰寫後端程式碼的情況下操作資料。

為了簡化起見,本教學課程會示範如何使用 Azure 資料庫進行本機開發,但您也可以在本機開發需求中使用本機資料庫伺服器。

附註

本教學課程會示範如何使用 Azure Database for PostgreSQL 彈性伺服器或單一伺服器。 如果您想要使用其他資料庫,請參閱 Azure Cosmos DBAzure SQLMySQL 教學課程。

Web 瀏覽器顯示開發人員工具主控台視窗中從 PostgreSQL 選取的結果。

您會在本教學課程中學到:

  • 將 Azure Database for PostgreSQL 彈性伺服器或單一伺服器資料庫連結到您的靜態 Web 應用程式
  • 建立、讀取、更新及刪除資料

先決條件

若要完成本教學課程,您需要已存在的 Azure Database for PostgreSQL 彈性伺服器或單一伺服器,以及靜態 Web 應用程式。 此外,你需要安裝 Visual Studio Code。

資源 描述
Azure Database for PostgreSQL 彈性伺服器Azure Database for PostgreSQL 單一伺服器資料庫 如果您還沒有,請依照建立 Azure Database for PostgreSQL 彈性伺服器資料庫指南中的步驟操作,或依照建立 Azure Database for PostgreSQL 單一伺服器資料庫指南中的步驟操作。 如果您打算對 Static Web Apps 的資料庫連線使用連線字串驗證,請確保您以 PostgreSQL 驗證建立 Azure Database for PostgreSQL 伺服器。 如果您稍後想改用受控識別,可以變更此值。
既有的靜態 Web 應用程式 如果您還沒有,請依照開始使用指南中的步驟建立無架構的靜態 Web 應用程式。
Visual Studio Code,搭配 PostgreSQL 擴充功能 如果你還沒安裝 Visual Studio Code,請依照指南安裝 Visual Studio Code,並搭配 PostgreSQL 擴充功能。 或者,您也可以使用任何其他工具來查詢 PostgreSQL 資料庫,例如 PgAdmin。

請先設定資料庫,使其可與 Azure Static Web Apps 的資料庫連線功能搭配運作。

設定資料庫連線能力

Azure Static Web Apps 必須能透過網路存取您的資料庫,資料庫連線才會運作。 此外,若要在本機開發使用 Azure 資料庫,您需要設定資料庫以允許來自您自己 IP 位址的要求。

  1. 前往 Azure 入口網站中的 Azure Database for PostgreSQL 伺服器。

  2. 如果您使用 Azure Database for PostgreSQL 彈性伺服器,請在設定區段下選取網路。 如果您使用 Azure Database for PostgreSQL 單一伺服器,請在設定區段下選取連線安全性

  3. 防火牆規則區段下,選取新增您目前的用戶端 IP 位址按鈕。 此步驟可確保您能將此資料庫用於本機開發。

  4. 防火牆規則區段下,選取允許 Azure 中任何 Azure 服務對此伺服器進行公共存取核取方塊。 如果您使用 Azure Database for PostgreSQL 單一伺服器,此切換的標籤為允許存取 Azure 服務。 此步驟可確保您部署的 Static Web Apps 資源能存取您的資料庫。

  5. 選取儲存

取得本機開發的資料庫連線字串

若要在本機開發使用 Azure 資料庫,您需要擷取資料庫的連線字串。 如果您打算使用本機資料庫進行開發,可以略過此步驟。

  1. 前往 Azure 入口網站中的 Azure Database for PostgreSQL 伺服器。

  2. 設定區段下,選取連線字串

  3. ADO.NET 方塊複製連線字串,並在文字編輯器中先保留。

  4. 將連線字串中的 {your_password} 預留位置替換為您的密碼。

  5. {your_database} 預留位置替換為資料庫名稱 MyTestPersonDatabase。 您會在接下來的步驟中建立 MyTestPersonDatabase

  6. Trust Server Certificate=True; 附加到連線字串,以便使用此連線字串進行本機開發。

建立範例資料

建立範例資料表並植入範例資料,以符合教學課程內容。 這個教學使用 Visual Studio Code,但你也可以使用 PgAdmin 或其他工具。

  1. 在 Visual Studio Code 中, 建立與 Azure Database for PostgreSQL Server 的連接

  2. 以滑鼠右鍵按一下您的伺服器,然後選取新增查詢。 執行下列查詢以建立名為 MyTestPersonDatabase 的資料庫。

    CREATE DATABASE "MyTestPersonDatabase";
    
  3. 以滑鼠右鍵按一下您的伺服器,然後選取重新整理

  4. 以滑鼠右鍵按一下 MyTestPersonDatabase,然後選取新增查詢。 執行下列查詢以建立名為 MyTestPersonTable 的新資料表。

    CREATE TABLE "MyTestPersonTable" (
        "Id" SERIAL PRIMARY KEY,
        "Name" VARCHAR(25) NULL
    );
    
  5. 執行下列查詢,將資料新增到 MyTestPersonTable 資料表中。

    INSERT INTO "MyTestPersonTable" ("Name")
    VALUES ('Sunny');
    
    INSERT INTO "MyTestPersonTable" ("Name")
    VALUES ('Dheeraj');
    

設定靜態 Web 應用程式

本教學課程其餘部分著重於編輯靜態 Web 應用程式的原始程式碼,以在本機使用資料庫連線。

重要事項

下列步驟假設您正在使用開始使用指南中建立的靜態 Web 應用程式。 如果您使用不同的專案,請務必調整下列 git 命令以符合您的分支名稱。

  1. 切換至 main 分支。

    git checkout main
    
  2. 使用 git pull 將您的本機版本與 GitHub 上的內容同步。

    git pull origin main
    

建立資料庫組態檔

接下來,建立靜態 Web 應用程式用來與資料庫介接的組態檔。

  1. 開啟您的終端機並建立新變數來儲存您的連線字串。 實際語法可能會因您使用的殼層類型而有所不同。

    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 install -g @azure/static-web-apps-cli
    

    若要更新,請使用 npm update

    npm update
    
    npm update
    
  3. 使用 swa db init 命令來產生資料庫組態檔。

    swa db init --database-type postgresql
    

    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": "postgresql",
    "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 文件

功能 說明
資料庫連線 在開發期間,執行階段會從組態檔中的連線字串值讀取連線字串。 雖然您可以直接在組態檔中指定連線字串,但最佳做法是將連線字串儲存在本機環境變數中。 您可以透過 @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-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>

在本機啟動應用程式

現在您可以執行網站,並直接操作資料庫中的資料。

  1. 使用資料庫組態在本機啟動靜態 Web 應用程式。

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

CLI 啟動後,您可以透過 staticwebapp.database.config.json 檔案中所定義的端點存取資料庫。

hthttp://localhost:4280/data-api/rest/<ENTITY_NAME> 端點接受 GETPUTPOSTDELETE 要求,以便操作資料庫中的資料。

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

操作資料

下列與架構無關的命令示範如何對資料庫執行完整的 CRUD 作業。

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

按下 CMD/CTRL + SHIFT + I 開啟開發人員工具,然後選取主控台索引標籤。

列出所有項目

將下列程式碼新增到 index.htmlscript 標記之間。

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

以下是螢幕擷取畫面,顯示在您的瀏覽器中應該呈現的樣子。

Web 瀏覽器顯示開發人員工具主控台視窗中從資料庫選取的結果。

依識別碼取得

將下列程式碼新增到 index.htmlscript 標記之間。

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 名稱
1 Sunny

更新

將下列程式碼新增到 index.htmlscript 標記之間。

Static Web Apps 同時支援 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 Molly

建立

將下列程式碼新增到 index.htmlscript 標記之間。

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 Pedro

刪除

將下列程式碼新增到 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 應用程式

使用下列步驟在網站的 Static Web Apps 執行個體與資料庫之間建立連線。

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

  2. 設定區段中,選取資料庫連線

  3. 生產環境區段中,選取連結現有資料庫連結。

  4. 連結現有資料庫視窗中,輸入下列值:

    屬性
    資料庫類型 從下拉式清單選取您的資料庫類型。
    訂用帳戶 從下拉式清單選取您的 Azure 訂用帳戶。
    資源名稱 選取具有您所需資料庫的資料庫伺服器名稱。
    資料庫名稱 選取您要連結到靜態 Web 應用程式的資料庫名稱。
    驗證類型 選取連線字串,然後輸入 PostgreSQL 使用者名稱和密碼。 若是 PostgreSQL 單一伺服器,請不要包含 @servername 尾碼。
  5. 選取確定

確認您的資料庫已連線至您的 Static Web Apps 資源

當您將資料庫連線到靜態 Web 應用程式,且網站完成建置後,請使用下列步驟確認資料庫連線。

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

  2. 基本資訊區段中,選取您的 Static Web Apps 資源的 URL,以瀏覽至您的靜態 Web 應用程式。

  3. 選取列出按鈕以列出所有項目。

    輸出應類似此螢幕擷取畫面所示的內容。

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

清除資源

如果您想要移除此教學課程期間建立的資源,您需要取消連結資料庫並移除範例資料。

  1. 取消連結資料庫:在 Azure 入口網站中開啟您的靜態 Web 應用程式。 在設定區段下,選取資料庫連線。 在已連結的資料庫旁,選取檢視詳細資料。 在資料庫連線詳細資料視窗中,選取取消連結按鈕。

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

後續步驟