このチュートリアルでは、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 アプリが必要です。 さらに、Visual Studio Code をインストールする必要があります。
| リソース | Description |
|---|---|
| Azure Database for MySQL フレキシブル サーバー | データベースを作成する必要がある場合は、「 Azure Database for MySQL フレキシブル サーバーの作成 」ガイドの手順に従ってください。 Web アプリに接続文字列認証を使用する場合は、MySQL 認証を使用してデータベースを作成してください。 後でマネージド ID を使用する場合は、後でこの設定を変更できます。 |
| 既存の静的 Web アプリ | まだない場合は、 ファースト ステップ ガイドの手順に従って、 No Framework 静的 Web アプリを作成します。 |
| Visual Studio Code と MySQL シェル拡張機能 | Visual Studio Code をまだインストールしていない場合は、ガイドに従って 、MySQL シェル拡張機能を使用して Visual Studio Code をインストールします。 または、MySQL Workbench などの他のツールを使用して MySQL データベースのクエリを実行することもできます。 |
まず、Azure Static Web Apps データベース接続機能を使用するようにデータベースを構成します。
データベース接続の構成
データベース接続を機能させるには、Azure Static Web Apps にデータベースへのネットワーク アクセス権が必要です。 さらに、ローカル開発に Azure データベースを使用するには、独自の IP アドレスからの要求を許可するようにデータベースを構成する必要があります。
Azure portal で Azure Database for MySQL Server フレキシブル サーバーに移動します。
[設定] セクションで、[ネットワーク] を選択します。
[ ファイアウォール規則 ] セクションで、[ 現在のクライアント IP アドレスの追加 ] ボタンを選択します。 この手順により、このデータベースをローカル開発に使用できるようになります。
[ ファイアウォール規則 ] セクションで、[ Azure 内の任意の Azure サービスからこのサーバーへのパブリック アクセスを許可する ] チェック ボックスをオンにします。 この手順により、デプロイされた静的 Web Apps リソースがデータベースにアクセスできるようになります。
保存 を選択します。
ローカル開発用のデータベース接続文字列を取得する
ローカル開発に Azure データベースを使用するには、データベースの接続文字列を取得する必要があります。 開発目的でローカル データベースを使用する場合は、この手順を省略できます。
Azure portal で Azure Database for MySQL Server フレキシブル サーバーに移動します。
[ 設定] セクションで、[ 接続] を選択します。
[ アプリからの接続 ] セクションで、ADO.NET 接続文字列を選択し、テキスト エディターに保存します。
接続文字列の
{your_password}プレースホルダーをパスワードに置き換えます。{your_database}プレースホルダーをデータベース名のMyTestPersonDatabaseに置き換えます。 次の手順でMyTestPersonDatabaseを作成します。接続文字列の SslMode セクションと SslCa セクションは、追加の手順が必要であり、運用環境向けであるため、削除します。
サンプル データの作成
サンプル テーブルを作成し、チュートリアルに合わせてサンプル データをシード処理します。 ここでは Visual Studio Code を使用できますが、MySQL Workbench やその他のツールを使用することもできます。
Visual Studio Code と MySQL Shell 拡張機能で、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 アプリのソース コードを編集して、データベース接続をローカルで利用することに重点を置いています。
Important
次の手順では、 ファースト ステップ ガイドで作成した静的 Web アプリを使用していることを前提としています。 別のプロジェクトを使用している場合は、ブランチ名と一致するように次の git コマンドを調整してください。
mainブランチに切り替えます。git checkout maingit pullを使用して、ローカル バージョンを GitHub 上のバージョンと同期します。git pull origin main
データベース構成ファイルを作成する
次に、静的 Web アプリがデータベースとのインターフェイスに使用する構成ファイルを作成します。
ターミナルを開き、接続文字列を保持する新しい変数を作成します。 特定の構文は、使用しているシェルの種類によって異なる場合があります。
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 updateswa db initコマンドを使用して、データベース構成ファイルを生成します。swa db init --database-type mysqlinitコマンドは、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"
}
]
}
}
}
次の手順に進む前に、構成ファイルのさまざまな側面を説明する次の表を確認してください。 構成ファイルの完全なドキュメントについては、 Data API Builder のドキュメントを参照してください。
| 特徴 | Explanation |
|---|---|
| データベース接続 | 開発中、ランタイムは、構成ファイル内の接続文字列の値から接続文字列を読み取ります。 接続文字列は構成ファイルで直接指定できますが、ローカル環境変数に接続文字列を格納することをお勧めします。
@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 に設定されます。 これらのオーバーライドにより、開発ワークロードと運用ワークロード全体で構成ファイルの一貫性が確保されますが、データベース接続が有効になっている静的 Web Apps リソースはセキュリティで保護され、運用に対応できます。
データベースに接続するように構成された静的 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>
アプリケーションをローカルで起動する
Web サイトを実行し、データベース内のデータを直接操作できるようになりました。
データベース構成で静的 Web アプリを起動します。
swa start --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 操作を実行する方法を示しています。
各関数の出力がブラウザーのコンソール ウィンドウに表示されます。
+ 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);
}
この例では:
-
fetchAPI の既定の要求では、動詞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 | Sunny |
| 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プロパティにあります。
ページを更新し、[ 取得 ] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、データベースから要求された 1 つのレコードを一覧表示するテーブルが表示されるようになりました。
| ID | 名前 |
|---|---|
| 1 | Sunny |
Update
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 | モリー |
Create
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 | ペドロ |
削除
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 アプリにデータベースを接続する
サイトの静的 Web Apps インスタンスとデータベースの間に接続を作成するには、次の手順に従います。
Azure portal で静的 Web アプリを開く
[ 設定] セクションで、[ データベース接続] を選択します。
[ 運用 ] セクションで、[ 既存のデータベースのリンク ] リンクを選択します。
[ 既存のデータベースのリンク ] ウィンドウで、次の値を入力します。
プロパティ 価値 データベースの種類 ドロップダウン リストからデータベースの種類を選択します。 Subscription ドロップダウン リストから Azure サブスクリプションを選択します。 リソース名 目的のデータベースを含むデータベース サーバー名を選択します。 データベース名 静的 Web アプリにリンクするデータベースの名前を選択します。 認証の種類 [ 接続文字列] を選択し、MySQL のユーザー名とパスワードを入力します。 [OK] を選択.
データベースが静的 Web Apps リソースに接続されていることを確認する
静的 Web アプリにデータベースを接続し、サイトの構築が完了したら、次の手順に従ってデータベース接続を確認します。
Azure portal で静的 Web アプリを開く
[ 要点 ] セクションで、静的 Web Apps リソースの URL を 選択して、静的 Web アプリに移動します。
[ リスト ] ボタンを選択して、すべての項目を一覧表示します。
出力は、このスクリーンショットに示されている内容のようになります。
リソースをクリーンアップする
このチュートリアルで作成したリソースを削除する場合は、データベースのリンクを解除し、サンプル データを削除する必要があります。
データベースのリンクを解除する: Azure portal で静的 Web アプリを開きます。 [ 設定] セクションで、[ データベース接続] を選択します。 リンクされたデータベースの横にある [ 詳細の表示] を選択します。 [ データベース接続の詳細 ] ウィンドウで、[ リンク解除 ] ボタンを選択します。
サンプル データの削除: データベースで、
MyTestPersonTableという名前のテーブルを削除します。