チュートリアル: Azure Static Web Apps で Azure SQL データベース接続を追加する (プレビュー)
このチュートリアルでは、静的 Web アプリに Azure SQL データベースを接続する方法について説明します。 構成しておくと、組み込みの /data-api
エンドポイントに対して REST または GraphQL 要求を行うことで、バックエンド コードを記述しなくてもデータを操作できます。
わかりやすくするために、このチュートリアルでは、ローカル開発の目的で Azure データベースを使用する方法について説明しますが、ローカル開発のニーズのためにローカル データベース サーバーを使用することもできます。
注意
このチュートリアルでは、Azure SQL を使用する方法について説明します。 別のデータベースを使用する場合は、Azure Cosmos DB、MySQL、または PostgreSQL のチュートリアルを参照してください。
このチュートリアルで学習する内容は次のとおりです。
- Azure SQL データベースを静的 Web アプリにリンクする
- データの作成、読み取り、更新、削除を行う
前提条件
このチュートリアルを完了するには、既存の Azure SQL データベースと静的 Web アプリが必要です。
リソース | 説明 |
---|---|
Azure SQL Database | まだない場合は、「単一データベースを作成する」ガイドの手順に従います。 |
既存の静的 Web アプリ | まだない場合は、ファースト ステップ ガイドの手順に従います。 |
まず、Azure Static Web Apps データベース接続機能を使用するようにデータベースを構成します。
データベース接続を構成する
データベース接続が機能するためには、Azure Static Web Apps がデータベースにネットワーク アクセスできる必要があります。 さらに、ローカル開発のために Azure データベースを使用するには、自分の IP アドレスからの要求を許可するようにデータベースを構成する必要があります。
Azure portal で Azure SQL Server に移動します。
[セキュリティ] セクションで、[ネットワーク] を選択します。
[パブリック アクセス] タブの [パブリック ネットワーク アクセス] の横で、[選択されたネットワーク] を選択します。
[ファイアウォール規則] セクションで、[クライアント IPv4 アドレスの追加] ボタンを選択します。 この手順により、ローカル開発のためにこのデータベースを使用できるようになります。
[例外] セクションで、[Azure サービスおよびリソースにこのサーバーへのアクセスを許可する] チェックボックスをオンにします。 この手順により、デプロイされた Static Web Apps リソースはデータベースにアクセスできるようになります。
[保存] を選択します。
ローカル開発用のデータベース接続文字列を取得する
Azure データベースをローカル開発に使用するには、データベースの接続文字列を取得する必要があります。 開発の目的でローカル データベースを使用する予定の場合は、この手順を省略できます。
Azure portal で Azure SQL Server に移動します。
[設定] セクションで、[SQL データベース] を選択します。
このチュートリアル用に作成した SQL データベースを選択します。
[設定] セクションで、[接続文字列] を選択します。
[ADO.NET (SQL 認証)] ボックスから、接続文字列をコピーし、テキスト エディターに貼り付けておきます。
接続文字列内の {your_password}
プレースホルダーを、ご使用のパスワードに置き換えてください。
サンプル データの作成
サンプル テーブルを作成し、チュートリアルと一致するサンプル データを使用してシード処理します。
左側のナビゲーション ウィンドウで、[クエリ エディター] を選択します。
Active Directory アカウントまたはサーバーのユーザー名とパスワードを使用して、サーバーにサインインします。
次のスクリプトを実行して、
MyTestPersonTable
という名前の新しいテーブルを作成します。CREATE TABLE [dbo].[MyTestPersonTable] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Name] VARCHAR (25) NULL, PRIMARY KEY (Id) );
次のスクリプトを実行して、MyTestPersonTable テーブルにデータを追加します。
INSERT INTO [dbo].[MyTestPersonTable] (Name) VALUES ('Sunny'); INSERT INTO [dbo].[MyTestPersonTable] (Name) VALUES ('Dheeraj');
静的 Web アプリを構成する
このチュートリアルの残りの部分では、ローカルでデータベース接続を使用するように静的 Web アプリのソース コードを編集することに重点を置いています。
重要
次の手順では、ファースト ステップ ガイドで作成した静的 Web アプリを使用していることを前提としています。 別のプロジェクトを使用している場合は、ブランチ名と一致するように次の git コマンドを調整してください。
main
ブランチに切り替えます。git checkout main
git 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 update
swa db init
コマンドを使用して、データベース構成ファイルを生成します。swa db init --database-type mssql
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": "mssql",
"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": "dbo.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-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 サイトを実行し、データベース内のデータを直接操作することができるようになりました。
データベース構成を使用して静的 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
プロパティにあります。
ページを更新し、[取得] ボタンを選択します。
ブラウザーのコンソール ウィンドウに、データベースから要求された 1 つのレコードを一覧表示するテーブルが表示されるようになりました。
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
オブジェクトでは、GraphQL クエリがquery
プロパティ内に保持されます。- 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
オブジェクトでは、GraphQL クエリがquery
プロパティ内に保持されます。- 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
オブジェクトでは、GraphQL クエリがquery
プロパティ内に保持されます。- 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 portal で静的 Web アプリを開く
[設定] セクションで、[データベース接続] を選択します。
[運用] セクションで、[既存のデータベースのリンク] リンクを選択します。
[既存のデータベースのリンク] ウィンドウで、次の値を入力します。
プロパティ 値 データベースの種類 ドロップダウン リストからデータベースの種類を選択します。 サブスクリプション ドロップダウン リストから Azure サブスクリプションを選択します。 リソース グループ データベース用のリソース グループを選択または作成します。 リソース名 目的のデータベースが含まれているデータベース サーバー名を選択します。 データベース名 静的 Web アプリにリンクするデータベースの名前を選択します。 認証の種類 [接続文字列] を選択し、Azure SQL のユーザー名とパスワードを入力します。 [OK] を選択します。
データベースが Static Web Apps リソースに接続されていることを確認する
静的 Web アプリにデータベースを接続し、サイトの構築が完了したら、次の手順に従ってデータベース接続を確認します。
Azure portal で静的 Web アプリを開く
[要点] セクションで、Static Web Apps リソースの [URL] を選択して、静的 Web アプリに移動します。
[一覧表示] ボタンを選択して、すべての項目を一覧表示します。
出力は、こちらのスクリーンショットのようになります。
リソースをクリーンアップする
このチュートリアルで作成したリソースを削除する場合は、データベースのリンクを解除し、サンプル データを削除する必要があります。
データベースのリンク解除: Azure portal で静的 Web アプリを開きます。 [設定] セクションで、[データベース接続] を選択します。 リンクされたデータベースの横で、[詳細の表示] を選択します。 [データベース接続の詳細] ウィンドウで、[リンク解除] ボタンを選択します。
サンプル データの削除: データベースで、
MyTestPersonTable
という名前のテーブルを削除します。