演習 - 既存のデータベースからリバース エンジニアリングする
Contoso Pizza のマネージャーから、同社がアプリでクーポンを表示できるようにエンドポイントを追加するよう求められました。 クーポンは既存のデータベースに存在します。 このユニットでは、既存のデータベースからスキャフォールディングを作成し、結果のエンティティ クラスを変更します。
キャンペーン データベースを検査する
これから、スキャフォールディングされたコードの生成に使用するデータベースを調べます。
[エクスプローラー] ペインで、Promotions ディレクトリを展開し、Promotions.db ファイルを右クリックして、[データベースを開く] を選びます。
[SQLite エクスプローラー] フォルダーで新しいデータベースが開きます。
[Sqlite エクスプローラー] フォルダーで、Promotions.db ノードと Coupons ノードを展開します。 データ スキーマに注意してください。
Coupons ノードを右クリックして、[Show table](テーブルの表示) を選びます。 クーポン データを調べます。
キャンペーン コンテキストとクーポン モデルをスキャフォールディングする
次に、データベースを使ってコードをスキャフォールディングします。
次のコマンドを実行します。
dotnet ef dbcontext scaffold "Data Source=Promotions/Promotions.db" Microsoft.EntityFrameworkCore.Sqlite --context-dir Data --output-dir Models
上記のコマンドでは次のことが行われます。
- 提供された接続文字列を使って、
DbContext
とモデルのクラスをスキャフォールディングします。 Microsoft.EntityFrameworkCore.Sqlite
データベース プロバイダーを使うように指定します。- 結果の
DbContext
とモデルのクラスを格納するディレクトリを指定します。
Note
この演習では、接続文字列がソース コードに含まれていることに関する警告は無視してかまいません。 実際のコードでは、接続文字列はセキュリティで保護された場所に必ず格納してください。
- 提供された接続文字列を使って、
Models\Coupon.cs を開き、スキャフォールディングされたモデルを調べます。
using System; using System.Collections.Generic; namespace ContosoPizza.Models { public partial class Coupon { public int Id { get; set; } public string Description { get; set; } = null!; public DateOnly? Expiration { get; set; } } }
SQLite は C# と比較して型のセットが限られているため、スキャフォールディング ツールでは、使用する C# 型について推論が行われました。 たとえば、SQLite には date データ型がないため、
Expiration
データベース列は文字列として定義されています。 データベース内のデータに基づいて、スキャフォールディング ツールにより C# 型はDateOnly?
になるものと推定されました。ヒント
データベースが変更された場合は、新しいスキャフォールディングされたファイルを生成できます。 ファイルは生成されるたびに上書きされますが、
partial
クラスとして作成されるので、独自の別のファイル内でカスタムのプロパティと動作を使用して拡張することができます。
クーポン エンドポイントを追加する
スキャフォールディングされたコードをテストする前に、API にエンドポイントを追加する必要があります。 そこで次に、新しい API コントローラーを追加します。
API コントローラーのしくみを理解するには、「ASP.NET Core コントローラーを使用して Web API を作成する」を参照してください。
Controllers フォルダーに、次のコードを含む CouponController.cs という名前のファイルを追加します。
using ContosoPizza.Data; using ContosoPizza.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace ContosoPizza.Controllers; [ApiController] [Route("[controller]")] public class CouponController : ControllerBase { PromotionsContext _context; public CouponController(PromotionsContext context) { _context = context; } [HttpGet] public IEnumerable<Coupon> Get() { return _context.Coupons .AsNoTracking() .ToList(); } }
このコードは、API に
api/coupon
エンドポイントを追加します。上のコードでは以下の操作が行われます。
PromotionsContext
オブジェクトが、コンストラクターに挿入されます。Get
メソッドから、すべてのクーポンが返されます。
Program.cs で、コメント
// Add the PromotionsContext
を次のコードに置き換えます。builder.Services.AddSqlite<PromotionsContext>("Data Source=Promotions/Promotions.db");
このコードは、
PromotionsContext
を依存関係挿入システムに登録します。すべての変更を保存し、
dotnet run
を使ってアプリを実行します。
エンドポイントをテストする
これでエンドポイントが追加されたので、クーポンの操作をテストします。
前の演習で行ったように、API の Swagger UI に移動します (または、ブラウザーで既存の UI を更新します)。
見出し [クーポン] の下で、[GET] 操作を展開し、[試してみる] ボタンを選択します。
[実行] を選択します。 応答本文に、データベースからのクーポンが表示されます。
[ { "id": 1, "description": "Buy 1 get 1 free", "expiration": "2025-01-01T00:00:00" }, { "id": 2, "description": "4 large pizzas for $40", "expiration": "2024-06-30T00:00:00" } ]
expiration
は datetime 値であることに注意してください。
これで完了です。 既存のデータベースからスキャフォールディングを作成して変更しました。