1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【ASP.NET】Web未経験者がASPのMSDNチュートリアルやってみる(DB操作)

Posted at

筆者のステータスはこんな感じ。

  • VB.NET経験あり
  • C#独学
  • Web未経験(何それおいしいの?)

時代はWebだということで、手を出してみます。
手を出すチュートリアルはコチラ。

今回はMSDNのチュートリアル「データベースの操作」を進めます。

※チュートリアルのパート3は説明会なので飛ばしました。

尚、前回実施した「【ASP.NET】Web未経験者がASPのMSDNチュートリアルやってみる(モデルの追加)」の続きから始めます。

#作成の流れ
まずは今回の作成の流れを確認します。MSDNのチュートリアルに沿って次の様に進めます。

  1. データベース接続
  2. データベースのシード
  3. シード初期化子の追加
  4. 実行

今回のチュートリアルも簡単そうに見えますね。

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 オブジェクト エクスプローラー」を選択します。
20220225_001.png
すると、Visual Studio の画面左側に、新しく「SQL Server オブジェクト エクスプローラー」が表示されます。
20220225_002.png
次に、「(localdb)\MSSQLLocalDB」→「データベース」→「RazorPagesMovieContext-xxxx(キー)」→「テーブル」の順に開き、「dbo.Movie」を右クリックして「デザイナーの表示」を選択します。
20220225_003.png
すると、テーブルの定義が表示されます。
20220225_004.png
この定義は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」を右クリックして「データの表示」を選択します。
20220225_005.png

すると、テーブルのデータが表示されます。
20220225_006.png
チュートリアルで作成したデータはここで見ることが出来ます。

2.データベースのシード

引き続き、MSDNのチュートリアルに沿って進めます。
次に出て来るのは「データベースのシード」について。

いきなり出てきましたシード。シードとは英語で種という意味ですが、ここでは初期のサンプルデータのことを指します。
RazorPagesMovie プロジェクトに「SeedData」フォルダを作成し、その中に「SeedData」クラスを作成します。
「SeedData」フォルダを作成して…
20220225_007.png
20220225_008.png
「SeedData」クラスを作成(「SeedData.cs」ファイルが作成されます)。
20220225_009.png
20220225_010.png
20220225_011.png
そして、「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 に入ってみると…
20220225_012.png
残念ながら出来てませんね。
完成したからとりあえず実行した人はこうなります(私はなりました)。

さて、MSDNのチュートリアルに戻ると、「データベース内のレコードを削除しなさい」とあります。
なので、ブラウザから「Delete」をクリックして削除しておきます。
20220225_013.png
せっかく作ったデータが消えてしまいましたね。

ただ、本題はシードデータを追加する事です。
アプリを動かした状態で、システムトレイの「IIS Express」アイコンを右クリックします。
20220225_014.png
コンテキストメニューから「終了」(もしくは「サイトの停止」)を選択します。
20220225_015.png
すると、「すべてのワーカープロセスを停止して終了しますか?」とポップアップが出るので、迷わず「はい」を選択。
20220225_016.png
そしてF5キーを押して、https://localhost:xxxx/movies に入ってみると…
20220225_017.png
シードのデータが作成されていることがわかります。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?