CodeZine(コードジン)

特集ページ一覧

【Docker+.NETで作る見積書】DioDocs for Excelを使ったモダンな帳票アプリ開発

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2022/04/06 12:00

目次

サンプルデータベースの作成

 さて、この図3のプログラムをベースに、冒頭の図1に示した帳票を出力するサンプルを組み込んでいきます。簡単に済ませるとすれば、「何かボタンをクリックすると、いつも決まった帳票が出力される」というサンプルを作ることですが、帳票出力といえば、「データベースに格納されたデータを取り出して帳票を作りたい」ということが、ほとんどではないでしょうか。

 ここでは実用に寄せて、簡単なデータベースを作り、そこに格納されているデータを帳票出力するというサンプルを作ります。とはいえきちんとしたデータベースやページを作るとたいへんですし、それが本連載の目的ではないので、できるだけ簡素化します。

 ここでは、マイクロソフト社の下記のページにある手順に則り、「モデルのクラスを作り、そこからデータベース、テーブル、そして、初期ページの自動生成」までを実施します。下記の工程では、サンプルとして不必要なページが作られますが、そのあたりは目をつむります。話を簡単にするため、データベースには、事前にインストールや初期設定をしておく必要がないSQLiteを使います。

【手順】サンプルデータベースの作成

[1]EF Coreツールなどのインストール

 今回は、データベース操作に「Entity Framework(EF) Core」を使っていきます。そのためのツールやライブラリをインストールするため、次のコマンドを入力します。

dotnet tool install -g dotnet-aspnet-codegenerator
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SQLite
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design

 ツールは、ホームディレクトリの/.net/toolsフォルダにインストールされます。次のように入力して、パスを通しておきます。

export PATH="$PATH:/$HOME/.dotnet/tools"
[2]モデルを作る

 ツールの準備が整ったら、まずは、テーブルの基となる「モデル」を作ります。ここでは、「注文(Order)」と「明細(Detail)」の親子関係を持つテーブルとします。exampleappフォルダの下にModelsフォルダを作り、その下にリスト2の内容で、Models.csファイルを作ります。

[リスト2]Models/Models.cs
using System;
using System.ComponentModel.DataAnnotations;

namespace exampleapp.Models {
    public class Order {
        public int OrderID { get; set; }
        public string Zip { get; set;}
        public string Address1 {get; set;}
        public string Address2 {get; set;}
        public string Company {get; set;}
        public string Person {get; set;}
        public string Email {get; set;}
        [DataType(DataType.Date)]
        public DateTime OrderDate { get; set; }

        public ICollection<Detail> Details {get; set;}
    }

    public class Detail {
        public int ID { get; set; }
        public int OrderID {get; set;}
        public string ProductName { get; set;}
        public decimal UnitPrice {get; set;}
        public int Quantity {get; set;}
    }
}

 EF Coreで扱う場合、プロパティに命名規則があります。ここでは、次の命名規則に従っています。

  • 主キー:「ID」や「クラス名+ID」を付けると、それは主キーとして扱われます(「OrderID列」および「ID列」)。
  • リレーション:親子関係は、「ICollection<クラス名>」で構成します(OrderとDetailの関係)。子が親を参照する外部キーは、「クラス名+ID」で命名します(DetailクラスのOrderIDプロパティ)。
[3]ページを自動生成する

 このモデル定義から、データベースへの接続定義や一覧や編集、削除のページなど、必要なコード一式を自動で生成します。

 まずは、Orderテーブルについて、次のようにして作成します(ここでは「Pages/Orders」のように、-outDirオプションを「Orders」としている点に注意してください。Ordersである必要はないのですが、「Order」のようにモデルのクラス名と同じにすると「ページ名」と「モデルのクラス名」が同名になり、ビルド時にエラーが発生します)。

dotnet-aspnet-codegenerator razorpage -m Order -dc MyAppContext -udl -outDir Pages/Orders --referenceScriptLibraries -sqlite

 同様にして、Detailテーブルについて作成します。

$HOME/.dotnet/tools/dotnet-aspnet-codegenerator razorpage -m Detail -dc MyAppContext 
[4]データベースやテーブルを作る

 これでPagesフォルダ以下に、「Orders」と「Details」のフォルダができ「一覧(Index)」「新規作成(Create)」「編集(Edit)」「削除(Delete)」の4つのページが作成されます。しかしデータベースもテーブルもまだないので、実行して開いてもエラーが発生するだけです。そこでデータベースとテーブルを作成していきましょう。

 EF Coreには、このモデルから、自動でデータベースやテーブル自体を作成するマイグレーション機能があります。まず、次のように入力します。

dotnet ef migrations add InitialCreate

 するとMigrationディレクトリ以下に、データベースやテーブルを作成するためのプログラムが自動生成されます。これをデータベースに反映するため、下記のコマンドを入力します。このコマンド入力によって、実際にデータベースとテーブルが作成されます。

dotnet ef database update
[5]動作確認する

 この段階で動作確認しておきます。ビルドして起動します。

dotnet publish -c Release -o published
dotnet published/exampleapp.dll

 ブラウザで、「http://localhost:5000/Orders/」を開きます。すると、Orderテーブルの一覧が表示されます(図5)。ここで[Create New]のリンクをクリックすると、新しい注文を作成できますが、何もしないでおいてください(以下の手順では、「何もレコードが存在しないとき」に限って、初期データを作成するプログラムを作るため、何かデータを入れると次の手順で失敗します)。

図5 Orderテーブルの一覧が表示された
図5 Orderテーブルの一覧が表示された

初期データの投入

 まだテーブルの中身が空なので、サンプルのデータを投入します。いくつかのやり方がありますが、ここでは「何もレコードが存在しないとき」に限って、初期データを作成するプログラムを作ります。

 あまり手間をかけたくないので、Program.csをリスト3のように書き換えます。書き換えた箇所には「★印」を付けました。

[リスト3]Program.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
// ★追加★
using exampleapp.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddDbContext<MyAppContext>(options =>
    options.UseSqlite(builder.Configuration.GetConnectionString("MyAppContext")));

var app = builder.Build();

// ★初期化データ投入 ここから★
using (var scope = app.Services.CreateScope()){
    var services = scope.ServiceProvider;
    using (var context = services.GetRequiredService<MyAppContext>()) {
        if (!await context.Order.AnyAsync()) {
            var order = new Order {
                Zip = "123-4567",
                Address1 = "東京都新宿区",
                Address2 = "1-2-3 ●●ビル",
                Company = "株式会社●●",
                Person = "山田一郎",
                Email = "yamada@example.co.jp",
                OrderDate = DateTime.Today,
                Details = new List<Detail> {
                    new Detail{ ProductName = "製品A", UnitPrice = 100, Quantity = 5},
                    new Detail{ ProductName = "製品B", UnitPrice = 300, Quantity = 3},
                    new Detail{ ProductName = "製品C", UnitPrice = 400, Quantity = 1},
                }
            };
            context.Order.Add(order);
            await context.SaveChangesAsync();
        }
    }
}
// ★追加ここまで★

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

 このように修正してビルドして実行し、先ほどと同様に「http://localhost:5000/Orders/」を確認すると、初期データが入っていることがわかります(図6)。図6には表示されていませんが、実際には明細も入っています。

図6 初期データが入った
図6 初期データが入った

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:クラウド時代にマッチする、ドキュメント生成・更新APIライブラリ「DioDocs(ディオドック)」

もっと読む

著者プロフィール

  • 大澤 文孝(オオサワ フミタカ)

    テクニカル・ライター、プログラマ/システムエンジニア。情報セキュリティスペシャリスト、ネットワークスペシャリスト。入門書からプログラミングの専門書まで幅広く執筆。 &nbsp; 主な著作として、「Amazon Web Services 基礎からのネットワーク&am...

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5