筆者のステータスはこんな感じ。
- VB.NET経験あり
- C#独学
- Web未経験(何それおいしいの?)
時代はWebだということで、手を出してみます。
手を出すチュートリアルはコチラ。
今回はMSDNのチュートリアル「データベースの操作」を進めます。
※チュートリアルのパート3は説明会なので飛ばしました。
尚、前回実施した「【ASP.NET】Web未経験者がASPのMSDNチュートリアルやってみる(モデルの追加)」の続きから始めます。
#作成の流れ
まずは今回の作成の流れを確認します。MSDNのチュートリアルに沿って次の様に進めます。
- データベース接続
- データベースのシード
- シード初期化子の追加
- 実行
今回のチュートリアルも簡単そうに見えますね。
1.データベース接続
まずはデータベース接続の話。
MSDNのチュートリアルでは、RazorPagesMovieContext オブジェクトの説明が記載されています。
RazorPagesMovieContext オブジェクトは、データベースへの接続と、データベース レコードへの Movie オブジェクトのマッピングのタスクを処理します。 データベース コンテキストは、Startup.cs の メソッドで依存性の注入コンテナーに登録されます。
唐突に出て来るRazorPagesMovieContextオブジェクトというのは、DbContextクラスの派生クラスであるRazorPagesMovieContextクラスのことですね。
Startup.csの中を見ると、
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}
と記載されています。
services.AddDbContext はEntityFrameworkServiceCollectionExtensionsクラスの中に定義されています。
じゃあ、DBに接続する接続文字列はどこに書くのかというと、appsettings.jsonファイルの中で記載します。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-918ff605-1ec6-41e0-92e5-1c1a816338c5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
ConnectionStringsの後ろにキーを渡して、接続文字列を記載します。
実際にローカルに作られたDBを見てみます。
Visual Studio のメニューバー「表示」から「SQL Server オブジェクト エクスプローラー」を選択します。
すると、Visual Studio の画面左側に、新しく「SQL Server オブジェクト エクスプローラー」が表示されます。
次に、「(localdb)\MSSQLLocalDB」→「データベース」→「RazorPagesMovieContext-xxxx(キー)」→「テーブル」の順に開き、「dbo.Movie」を右クリックして「デザイナーの表示」を選択します。
すると、テーブルの定義が表示されます。
この定義はMovie.csで記述されているプロパティを元に、EntityFramework が自動で生成したものです。
Movie.csの最初に書かれているプロパティが主キーに設定されます。
namespace RazorPagesMovie.Models
{
public class Movie
{
public int ID { get; set; } //EntityFramework が自動で主キーに設定
public string Title { get; set; }
[DataType(DataType.Date)]public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
}
次にテーブルのデータを見てみます。
「dbo.Movie」を右クリックして「データの表示」を選択します。
すると、テーブルのデータが表示されます。
チュートリアルで作成したデータはここで見ることが出来ます。
2.データベースのシード
引き続き、MSDNのチュートリアルに沿って進めます。
次に出て来るのは「データベースのシード」について。
いきなり出てきましたシード。シードとは英語で種という意味ですが、ここでは初期のサンプルデータのことを指します。
RazorPagesMovie プロジェクトに「SeedData」フォルダを作成し、その中に「SeedData」クラスを作成します。
「SeedData」フォルダを作成して…
「SeedData」クラスを作成(「SeedData.cs」ファイルが作成されます)。
そして、「SeedData.cs」ファイルに以下を記述。
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
using System;
using System.Linq;
namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
if (context.Movie.Any())
{
return; // DB has been seeded
}
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}
「SeedData」クラスの記述を見て見ると、Initialize メソッドでcontext.Movie.AddRangeを実行し、引数には、プロパティを用意している「Movie」クラスのインスタンスを生成し、それぞれのプロパティに値をセットしていることが分かります。
つまり、「SeedData」クラスが使われると、自動的に初期データが用意されるはずです。
ただし、今回追加したクラスのため、この「SeedData」クラスを呼び出す必要があります。
3.シード初期化子の追加
先ほど作成した「SeedData」クラスを呼び出す記述を、「Program」クラスの Main メソッドに追加します。
チュートリアルだと差分が分かりにくいので、コメントアウトで追加・修正個所を記載しておきました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection; //追加
using RazorPagesMovie.Models; //追加
namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
//CreateHostBuilder(args).Build().Run(); //元々の記述
var host = CreateHostBuilder(args).Build(); //修正
//追加 start
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
//追加 end
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Main メソッド内に 先ほど追加した「SeedData」クラスの Initialize メソッドが呼び出されているので、シードの生成が可能となります。
4.実行
では、一度ビルドして実行してみます。
実行して、https://localhost:xxxx/movies に入ってみると…
残念ながら出来てませんね。
完成したからとりあえず実行した人はこうなります(私はなりました)。
さて、MSDNのチュートリアルに戻ると、「データベース内のレコードを削除しなさい」とあります。
なので、ブラウザから「Delete」をクリックして削除しておきます。
せっかく作ったデータが消えてしまいましたね。
ただ、本題はシードデータを追加する事です。
アプリを動かした状態で、システムトレイの「IIS Express」アイコンを右クリックします。
コンテキストメニューから「終了」(もしくは「サイトの停止」)を選択します。
すると、「すべてのワーカープロセスを停止して終了しますか?」とポップアップが出るので、迷わず「はい」を選択。
そしてF5キーを押して、https://localhost:xxxx/movies に入ってみると…
シードのデータが作成されていることがわかります。
参考