ちょいメモ。
ASP.NET CoreでEntityFrameWorkでSQLiteを使えるようにするところまで。
プロジェクトの準備
Visual Studio 2017から、今回は「ASP.NET Core Web API」としてプロジェクト作成。
.NET Core 2.0。
NuGetから以下のパッケージをインストールしておく。
・Microsoft.EntityFrameworkCore.Tools
・Microsoft.EntityFrameworkCore.Sqlite
テーブル準備
DbContextを継承したクラスを作成する。
この中でOnConfiguringをオーバーライドして、SQLiteデータファイルへの接続文字列を指定する。
SQLiteの接続文字列はとてもシンプルだ。
「data.db」というファイルをドキュメントルート直下に置く場合は以下のように。
public class MyDbContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseSqlite(@"Data Source='data.db'"); } }
ここではID, 年齢, 名前だけのPersonテーブルを作るとしましょう。
まず、そのレコードを格納するためのデータクラスを用意する。コードファースト。
public class Person { public int Id { get; set; } public int Age { get; set; } public string Name { get; set; } }
コンテキストクラスに、対応するDbSetプロパティを追加。
public class MyDbContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseSqlite(@"Data Source='data.db'"); } public DbSet<Person> Persons { get; set; } }
ここまでコードを作ってから、Microsoft.EntityFrameworkCore.Toolsを利用して、マイグレーションでテーブルを作成する。
Visual Studioのパッケージ・マネージャー・コンソールから、以下コマンドを実行。
PM> Add-Migration InitPersonTable PM> Update-Database
(「InitPersonTable」の部分は任意の名前)
Migrationsフォルダ配下のマイグレーション管理クラスと、SQLiteのデータファイル data.db が生成される。
テーブル読み書き
さて、ASP.NET Core Web APIのプロジェクトテンプレートには、以下のようなサンプルのコントローラクラスが用意されているかと思います。
[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/values/5 [HttpGet("{id}")] public string Get(int id) { return "value"; } // POST api/values [HttpPost] public void Post([FromBody]string value) { } // PUT api/values/5 [HttpPut("{id}")] public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 [HttpDelete("{id}")] public void Delete(int id) { } }
これを使って、getとpostを試してみましょう。
まずは、何もいじらずに立ち上げてみる。
Visual StudioからそのままIIS Expressでデバッグ起動でも良いけど、一応デプロイ用のファイルをローカルフォルダに出力してみる。
ソリューションエクスプローラーからプロジェクト右クリック > [発行] > [フォルダー]選んでパス入力 > [発行]
しかしこのままだとさっきのdata.dbが発行先にコピーされない。
これは自分でdata.db右クリック > [プロパティ] > [出力ディレクトリにコピー] で設定すんのかな。
発行されたら、dotnetコマンドで起動。
>dotnet プロジェクト名.dll
ブラウザから http://localhost:5000/api/values/1234 にアクセスしてみる。
サンプルのままなら、なんのIDを指定しても固定で「value」だけ表示されるはず。
では、ちゃんとPersonテーブルから名前を返しましょう。
IDを引数にとるgetメソッドを以下のように書き換える。
[HttpGet("{id}")] public IActionResult Get(int id) { using (var context = new MyDbContext()) { var person = context.Persons.FirstOrDefault(p => p.Id == id); if (person == null) return NotFound(); return new ObjectResult(person) as IActionResult; } }
もっかい立ち上げなおしてアクセスしてみる。
テーブルにはまだレコードがないので、404 NotFoundのページになればOK。
では、POSTでレコードを登録しましょう。
まずPostメソッドを以下のように書き換える。
[HttpPost] public IActionResult Post([FromBody]Person person) { if (person == null) return BadRequest(); using (var db = new MyDbContext()) { db.Persons.Add(person); db.SaveChanges(); } return CreatedAtRoute("values", new { id = person.Id }, person); }
Postの応答ではstatus 201で、新しく登録されたリソースへのルートを返すのが良いらしいので、上の例ではそのようにしている。
CreatedAtRouteの引数でvaluesというルート名を指定してるけど、この名前はGETメソッドのほうにつけておかないといけない。
[HttpGet("{id}", Name ="values")] public IActionResult Get(int id) { (省略) }
呼び出し例
では、このAPIの呼び出しも別アプリとして作ってみましょう。
適当なコンソールアプリで↓こんなのを。詳しくは HttpClientでJSONデータをPOSTする をどうぞ。
var person = "{ \"Id\" : 123, \"Age\" : 20, \"Name\" : \"鈴木一郎\" }"; using (var client = new HttpClient()) { var content = new StringContent(person, Encoding.UTF8, "application/json"); var res = client.PostAsync("http://localhost:5000/api/values", content).Result; Console.WriteLine(res); }
結果。
StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.NoWriteNoSeekStreamContent, Headers: { Date: Mon, 12 Feb 2018 10:00:33 GMT Transfer-Encoding: chunked Location: http://localhost:5000/api/Values/123 Server: Kestrel Content-Type: application/json; charset=utf-8 }
とりあえずここまで。
参考:
EntityFrameworkCoreを.NET Core コンソールアプリでCodeFirstに使う
ASP.NET Core と Visual Studio for Windows で Web API を作成する