【ASP.NET(C#)1】Vue.js+SQLServer(MSSQL)で画面表示

期間が空いてしまってすみません。GW前くらいからソシャゲのウマ娘にハマっていてスキルアップがおざなりになっていました。。

あ。もちろんもう飽きてしまって引退するのでこうしてまたスキルアップに時間を費やすことができます。

この記事のゴールはASP.NETとVue.jsを使ってデータベースであるSQLSERVERにデータベースとテーブルをインサートし、データを挿入した上で画面上に値が表示できるまでをやりたいと思います。

前回までのおさらい

ASP.NETとあまり選ばれないVue.jsの組み合わせでWebアプリの基礎を作ってみようと書いたのがこの記事です。

今回はこの記事の最後である下記画像を表示できるようになった所からスタートします。

やることリスト
  1. SQLSERVERを用意する
  2. EntityFrameworkCore をインストールする
  3. EntityFrameworkCore を使用するのに必要な処理を埋め込む
  4. SQLSERVERにテーブルとデータを挿入する
  5. ControllersでEntityFrameworkCore を使って中のデータをViewsに渡せるようにする
  6. Views側でRazor構文を使ってデータを表示する

SQLSERVERを用意する

まずはC#で使用するDBは基本的にSQLSERVER(MSSQL)なのでまずはSQL Serverを用意する必要があるのですが用意する方法には2種類あります。

記事が長くなってしまうことを防ぐため、具体的なインストール手順みたいなものはこちらでは割愛させて頂きます。

VS2019のオブジェクトエクスプローラー

一つはVS2019をインストールした時にプリインストールされていると思われる VS2019のオブジェクトエクスプローラー内にあるSQLSERVERです。

こちらの良いところはエクスプローラーを操作するのと同じ気持ちでデータベースやテーブルの追加が出来る所ですね。後々 EntityFrameworkCore をインストールした時に 接続情報を使ってこのDBにアクセスする事ができます。

SSMS(Microsoft SQL Server Management Studio)を使う

こちらはpgAdminWorkbenchと同じようなDB管理ツールでこちらをインストールする事でもDBをインストールすることができます。

色々試した感じ、どちらの環境でも設定がしっかりしていればLaravelにもあった、migrationコマンドが使用できて、データベースやテーブルを自動生成してくれます。ですのでローカルでデバッグする上ではどっちを使っても構いません。

まだ検証中ですがこの環境はあくまでローカルで使用するためか、Docker環境で動かした場合はうまく起動しませんでした。Docker環境だとあくまでUbuntu(Linux)になるのでWindowsのSQLSERVERに対応していないためと思われます。Docker環境でSQLServerを参照する方法はまた後日記事にします。

EntityFrameworkCore のインストール

EntityFrameworkCore の種類は色々あるものの、表題のようにただテーブルに入れた値を表示したいだけなら、 Microsoft.EntityFrameworkCore.SqlServerだけを入れればOKです。ただ、migraitonなど、他にも使いたい事ができた時は別途他のも入れる必要があるかもしれません。

参考までにNugetでパッケージをインストールした時は自動でプロジェクト名.csprojにも書かれますので現時点のcsprojの内容を下に記載しておきます。LaravelでいうPakage.jsonと同等の立場のファイルだと思っていますので要・不要を判断して入れましょう。

なお、パッケージマネージャを使わず、このcsprojに直接書いてもインストールすることが可能です。実務で最新以外のバージョンで統一している場合は既存のcsprojの内容をコピーしてパッケージを追加した方が事故が少ないと思います。

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    <DockerfileContext>.</DockerfileContext>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.13" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.8" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.13" />
  </ItemGroup>

</Project>

EntityFrameworkCore を動作させるのに必要な処理を埋め込む

EntityFrameworkを動かすのに追加しなきゃいけない処理は公式サイトに載っているくらい、構文が決まっている感じですので以下のリストを見て、用意しなきゃいけない事を頭に叩き込みましょう

  1. Models フォルダの下に任意のファイル名のContext.csファイルを作成する
  2. Models フォルダの下に使用するテーブル定義.csファイルを作成する
  3. appsettings.jsonにSQLServerの接続文字列を作成する
  4. Startup.csにてSQLServerに実際接続する処理を挿入する

Models フォルダの下に任意のファイル名のContext.csファイルを作る

アプリで使用するためのコンテキストを定義します。テーブル名は自分で作ったものを定義しますが書き方は固定なので覚えちゃってください。

ApplicationDbContext.cs

using Microsoft.EntityFrameworkCore;

namespace Aspnet_test2.Models
{
    /// <summary>
    /// DB との接続を行うためのコンテキストクラス
    /// </summary>
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {  }

        // モデルをセットする
        public DbSet<TestDb> TestDb { get; set; } 
    }
}

このソースのうち、ApplicationDbContextは任意の名称が可能。TestDbは自分が使用するテーブル名を定義します。

Models フォルダの下に テーブル名のファイルを作成

SQL Server側で作るテーブルと同じような内容のファイルを作成します。イメージ的にはこのファイルの型の通りにデータは読まれるし、書き込むための橋渡しもしていると考えてもらっていいと思います。

TestDb.cs

using System;

namespace Aspnet_test2.Models
{
    /// <summary>
    /// ASP.NET でEntity Frameworkを取れるようにするためのDB
    /// </summary>
    public class TestDb
    {
        /// <summary>
        /// ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// テスト文字列
        /// </summary>
        public string Test { get; set; }

        /// <summary>
        /// 更新日時
        /// </summary>
        public DateTime Update_Time { get; set; }
    }
}

中の3つのフィールドはDBでいうカラム相当です。この中とテーブルの型が合っていないとエラーが出ますので気を付けてください。

appsettings.jsonにSQLServerの接続文字列を作成する

前回の記事で自動生成した場合、appsettings.jsonというファイルができていると思いますのでここにSQLSERVERに接続するための文字列を追加します。こちらも2種類の接続文字列があります。

VS2019のオブジェクトエクスプローラー

appsettings.json

{
  "ConnectionStrings": {
    "DbContext": "Server=(localdb)\\mssqllocaldb;Database=INAKODB;Trusted_Connection=True;"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

SSMS で生成したSQLSERVER

前項ソースの“Server=(localdb)\mssqllocaldb;Database=INAKODB;Trusted_Connection=True;”“Server=localhost\SQLEXPRESS;Database=INAKODB;Trusted_Connection=True”に変更

ちなみに Trusted_Connection はローカルを使うという宣言でこれがない場合はちゃんとDBに接続するためのUSERIDとパスワードを入力する記述が必要です。このパターンはDockerを経由したSQLSERVER接続に必要になりそうですのでまた別途記事にするかもしれません。

Startup.csにてSQLServerに実際接続する処理を挿入する

前項で作った接続文字列を使って実際にSQLSERVERを呼び込む処理を作ります。こちらもほぼ定型文で公式サイトにも出ている構文ですので記憶してしまいましょう。

Startup.cs(ConfigureServices抜粋)

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders =
                    ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });

            services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DbContext")));
        }

こちらのソースで今回追加したのは11行目のみです。定義ファイル(appsettings.json)に示されたConnectionStringsにあるDbContextに書かれている文字列を使って接続します。という意味ですね。

EntityFrameworkを実際に使用するためには以上の4点を心掛けることを忘れないでください。

SQLSERVERにテーブルとデータを挿入する

前述したようにModelsで定義したテーブルはSQLSERVER側でも定義する必要があります。が、これは手動で作成してもいいですし、LaravelにもあったMigrationコマンドを使用すればSQLSERVER側はテーブルを自動生成してくれます。

Migrationコマンドを使用する時はMicrosoft.EntityFrameworkCore.Toolsが必要なので事前にインストールしておきましょう。

その後パッケージマネージャコンソールにて

> Add-Migration Initial
> Update-Database

を投入するだけです。

PM> Add-Migration Initial
Build started...
Build succeeded.
To undo this action, use Remove-Migration.
PM> Update-Database
Build started...
Build succeeded.
Done.

上記がうまくいけば接続文字列で示したDBが下記画像のように自動で登録されています。便利ですね☆

migrationは便利ではありますが、万が一Modelsの型の定義が誤っていた場合はその状態のままテーブルが作られてしまいます。開発時は手動でテーブルを作成してModelsとの突き合わせと確認を行ったあと、本番環境にデプロイする時だけmigrationを使った方が安心です。

データの挿入は他DB操作ツールとやり方変わらないのでここでは割愛し、次の項からはあらかじめデータが入っているものとして話を進めさせていただきますのでご了承ください。

ControllersでDBのデータをViewsに渡す

ここまで来たらあとは Controllers 側がDBのリードした値を拾ってViewsに受け渡すだけです。前回記事の操作通りにASP.NETの環境を作っているならControllersフォルダの下にはHomeController.csができているはずです。

HomeController.cs

using Aspnet_test2.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Aspnet_System_master.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly ApplicationDbContext _context;

        public HomeController(ApplicationDbContext context, ILogger<HomeController> logger)
        {
            _context = context;
            _logger = logger;
        }

        public async Task<IActionResult> Index()
        {
            return View(await _context.TestDb.ToListAsync());
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

マークがついている所が変更点です。軽く解説するとHomeControllerが親から呼び出される時にDBの内容をリードしてくれるのでそれをController内に保持してから該当の処理にそのデータを渡すだけです。awaitはDBの中をリードするまで待ってくれる処理で、これが無いと画面が表示されてから値が描画される危険があるのでつけています。

await/async/TaskもC#のWeb APIを作るうえで必須の技術ですがここでは詳細は割愛させて頂きます。

Views側でRazor構文を使ってデータを表示する

ここまででControllersに渡されたデータ中身がViewに引き渡されました。あとはView側で値を表示するだけです。Vue.jsも少し活かすためにちょっと元々の構文を変更してindex.cshtmlを修正してみました。

index.cshtml

@model IEnumerable<Aspnet_test2.Models.TestDb>

@{
    ViewData["Title"] = "Home Page";
}

<div id="app">
    <table>
        @foreach (var item in Model)
        {
        <tr>
            <td><h1 :class="error_class">@item.Id|</h1></td>
            <td><h1 :class="error_class">@item.Test|</h1></td>
            <td><h1 :class="error_class">@item.Update_Time|</h1></td>
        </tr>
        }
    </table>
</div>


@section Scripts {
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                error_class: "error"
            }
        })
    </script>
}

<style>
    .error {
        color: red;
    }
</style>

Vue.jsのCSS相当の文章(<style>)も使ってScriptで文字を赤にするように設定しました。先頭行はRazor構文Controllersから渡されたDBを使用したい時は上記のように宣言するのだそう。肝心の中身はHTMLと同じようにでき、foreachを使って、中のリストを全て表示しています。 まるで普通のC#をいじっているのと同じようにcshtmlを編集できるのですから Razor構文 って便利ですね☆

実行結果

DBの中身

ソリューションエクスプローラー

前回から追加になったのは四角い赤の二つ。migrationコマンドでDBを自動生成した場合はMigrationsフォルダも追加されます。

この章で変更・追加したソース

  • Controllers/HomeController.cs (DB周り変更)
  • Models/ApplicationDbContext.cs (新規追加)
  • Models/TestDb.cs (新規追加)
  • Views/Home/index.cshtml (データ表示)
  • appsettings.json (DB接続文字列の追加)
  • Startup.cs (DB接続処理の追加)
  • Microsoft.EntityFrameworkCore.SqlServer パッケージのインストール
  • Microsoft.EntityFrameworkCore.Tools パッケージのインストール

参考文献

・速習 ASP.NET Core 3 速習シリーズ Kindle版 著:山田 祥寛

Entity Framework Core の概要

これからはじめる人のJavaScript/Vue.jsの教科書 [ たにぐちまこと ]

まとめ

EntityFrameworkはやはりフレームワークで一定のルールに沿った使い方をしなければいけないので使いこなすまでは少し難しいですが、今までの手順を見て頂いてわかった通り、SQL文を書く必要が一切ないのは最大の利点です。

もちろん、SQLを書いて抽出することもあります。例えば検索条件を複数設定してDBを読みに行く時は後でLINQ使うよりも最初からSQL文を使って読む対象を絞った方がパフォーマンスが良いです。

今回は無事ローカル環境でSQLSERVERからデータを読んでVue.jsも織り交ぜて画面上に表示する所をやりました。

ただ、この構成だとSQLSERVERがWindows前提のため、Docker環境からだとエラーが出て起動できません。次はDocker環境でもデータを読んで表示できるようにしたいと思います。