SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ComponentZine(ComponentOne)byメシウス(AD)

【ComponentOne Data Services活用術】バッチ処理とEF Core連携でパフォーマンス向上

.NET対応のクラウドデータ連携ライブラリセット「ComponentOne Data Services」活用術 第3回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Entity Framework CoreでCRUD処理を実装

 ここでは、Windows Formsアプリを作成して、Entity Framework Core(以降、EF Core)とData Servicesの連携を見ていきましょう。EF Coreを使うと、データベースファーストのアプローチで、シンプルなコードでCRUD処理を実装できます。

Windows Formsアプリを作成する

 Windows Formsアプリを作成します。[新しいプロジェクトの作成]から、「Windows Formsアプリ」などを選択して、プロジェクト名には「EFCoreWinFormApp」などと適当な名前を指定してプロジェクトを作成します。

 必要なパッケージは、C1.EntityFrameworkCore.CSVです。データソースの利用に必要なC1.AdoNet.CSVパッケージは依存関係で自動的にインストールされます。

[NOTE]Scaffoldingの利用

 Microsoft.EntityFrameworkCore.Toolsパッケージをインストールして、Scaffoldingによりファイル群を作成する方法もあります。ただし、フィールド名がCSVの列名そのまま(マルチバイト文字)になるなどの問題点があるので、本記事では使用していません。

エンティティクラスを作成する

 EF Coreにおけるデータの入れ物となるエンティティクラスを作成しておきます。このデータクラスは、CSVファイルから返されるレコードの各フィールドを保持する役割を持ちます。プロジェクトのルートフォルダにData.csファイルを以下のような内容で作成します。

[リスト]:Data.cs
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFCoreWinFormsApp	(1)
{
  public partial class CustomerCSV	(2)
  {
    // CSVの列名とプロパティを対応付ける
    [Column("No")]	(3)
    public int Id { get; set; }	(4)
    [Column("氏名")]
    public string Name { get; set; }
    [Column("氏名(ひらがな)")]
    public string NameKana { get; set; }
    [Column("メールアドレス")]
    public string Email { get; set; }
    [Column("電話番号")]
    public string Tel { get; set; }
    [Column("郵便番号")]
    public string ZipCode { get; set; }
    [Column("住所")]
    public string Address { get; set; }
    [Column("会社名")]
    public string Company { get; set; }
  }
}

 (1)の名前空間の指定は、フォームのものと同じになるように指定してください(この場合はEFCoreWinFormsApp)。(2)では、クラスCustomerCSVを定義しています。これが、EF Coreにおけるデータの入れ物になります。partialキーワードによって部分クラスとしているのは、データモデルを自動生成した場合に、独自に追加するプロパティやビジネスロジックを分離するためです。今回はあえてpartialとする意味はないのですが、EF Coreにおけるエンティティクラスの一つの構成として押さえておくとよいでしょう。

 (3)では、CSVファイルにおける列名をSystem.ComponentModel.DataAnnotations.Schema.Column属性で指定しています。この属性と続く(4)のプロパティ定義において、列名とプロパティが結び付けられます。なお、EF CoreではIdプロパティは暗黙的に主キーと見なされるので、NoプロパティではなくIdプロパティとしています。

データベースコンテキストを作成する

 EF Coreでデータアクセスを担当し、データベースコンテキストクラスを作成します。同じくData.csファイルのEFCoreWinFormsApp名前空間に、以下のコードを追記します。

[リスト]:Data.cs
…略…
namespace EFCoreWinFormsApp
{
  …略…
  public partial class CSVContext : DbContext	(1)
  {
     // コンストラクタ。自動トランザクションを無効にする
     public CSVContext()	(2)
     {
       Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
    }
    public CSVContext(DbContextOptions<CSVContext> options)	(3)
      : base(options)
    {
      Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
    }
    // イベントハンドラからのデータベースコンテキストアクセスのためのプロパティ
    public virtual DbSet<CustomerCSV> CustomerCSV { get; set; }	(4)
    // データベースコンテキストの構築時に呼び出される。CSVファイルのURIを指定
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)	(5)
    {
      if (!optionsBuilder.IsConfigured)
      {
        optionsBuilder.UseCSV("Uri='customer.csv'");
      }
    }
    // モデルの作成時に呼び出される。エンティティを設定
    protected override void OnModelCreating(ModelBuilder modelBuilder)	(6)
    {
      modelBuilder.Entity<CustomerCSV>(entity =>
        {
          entity.ToTable("customer");
        });

      OnModelCreatingPartial(modelBuilder);
    }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
  }
}

 (1)で、データベースコンテキストクラスCSVContextを定義しています。このクラスは、Microsoft.EntityFrameworkCore.DbContextクラスを継承する必要があります。こちらも、部分メソッドの利用のためにpartialキーワードを付加して部分クラスとしています。

 (2)(3)はコンストラクタの定義です。オプションを渡せるオーバーロードも定義していますが、今回のサンプルでは使用していません。配下では、Database.AutoTransactionsBehaviorプロパティをNeverに指定して自動トランザクション処理を無効にしているだけです。

 (4)は、データセットプロパティの定義です。このプロパティを通じて、フォームからCSVファイルにアクセスします。(5)は、OnConfiguringメソッドのオーバライドです。データベースコンテキストの構築時に呼び出されます。引数として受けとったDbContextOptionsBuilderオブジェクトのUseCSVメソッドを使って、利用するCSVファイルの接続文字列を指定しています。

 (6)は、OnModelCreatingメソッドのオーバライドです。モデルの作成時に呼び出されます。引数として受け取ったModelBuilderオブジェクトを介してエンティティを設定します。ここでは、ToTableメソッドでCSVファイルに対応するテーブル名を指定しているだけですが、Propertyメソッドを使ってCSVファイルの列名とエンティティクラスのプロパティを対応付けることもできます。サンプルでは、Column属性で指定しているので、propertyメソッドの呼び出しは不要です。

フォームをレイアウトする

 データが準備できたら、フォームをレイアウトします。シンプルにDataGridViewコントロールと、データ保存とレコード削除のためのButtonコントロールを配置するだけです。配置は特に問いませんが、Anchorプロパティを設定し、ウィンドウのリサイズに追従させた方が見やすくなります(図4)。また、各列の幅を自動調整するAutoSizeColumnModeプロパティをAllCellsとしています。

図4:フォームへのコントロール配置後
図4:フォームへのコントロール配置後

Windows Formsアプリのコードを記述する

 イベントハンドラとして、DataGridViewコントロールへのバインドのコード、レコード削除とデータ保存のためのコードを用意します。内容はリストの通りです。

using System;
using System.Windows.Forms;
using Microsoft.EntityFrameworkCore;

namespace EFCoreWinFormsApp
{
  public partial class Form1 : Form
  {
    private CSVContext db = null;	(1)

    public Form()
    {
      InitializeComponent();
    }
    // フォームロード時にデータベースコンテキストを構築しデータソースを設定
    private void Form_Load(object sender, EventArgs e)	(2)
    {
      db = new CSVContext();
      db.CustomerCSV.Load<CustomerCSV>();
      dataGridView1.DataSource = db.CustomerCSV.Local.ToBindingList();
    }
    // 保存ボタンクリック。変更を保存
    private void SaveButton_Click(object sender, EventArgs e)	(3)
    {
      db.SaveChanges();
    }
    // フォームクローズ時にデータベースコンテキストを解放
    private void Form_FormClosed(object sender, FormClosedEventArgs e)	(4)
    {
      db.Dispose();
    }
    // 削除ボタンクリック。選択行の全てに削除を実行(新規の行を除く)
    private void RemoveButton_Click(object sender, EventArgs e)	(5)
    {
      foreach (DataGridViewRow row in dataGridView1.SelectedRows)
      {
        if (!row.IsNewRow)
        {
           dataGridView1.Rows.Remove(row);
        }
      }
    }
  }
}

 (1)では、データベースコンテキスト(Data.csファイルで定義したCSVContextクラス)を格納するためのprivateフィールドを準備しています。これで、フォーム中の任意のメソッドからデータベースを利用できるようになります。

 (2)は、フォームの作成時に呼び出されるイベントハンドラです。(1)のprivateフィールドにインスタンスを格納し、Loadメソッドでデータセットを読み込みます。読み込んだデータソースは、ToBindingListメソッドでDataGridViewコントロールに紐づけておきましょう。

 (3)は、保存ボタンクリック時に呼び出されるイベントハンドラです。データセットに変更がある場合には、SaveChangesメソッドで変更内容をCSVファイルに反映します。

 (4)は、フォームの破棄時に呼び出されるイベントハンドラです。データベースコンテキストオブジェクトをDisposeメソッドによって破棄します。

 (5)は、削除ボタンクリック時に呼び出されるイベントハンドラです。SelectedRowsプロパティによって選択されている行を取得し、その全ての行を、Removeメソッドで削除しています。ただし、IsNewRowプロパティで新規レコードは除外します。

 以上を理解できたら、アプリを実行してみましょう。あらかじめcustomer.csvを実行ファイルのある場所(例えばbin\Debug\net9.0-windowsフォルダなど)に配置しておきます。プロジェクトを実行するとアプリが起動するので、問題なければグリッドにCSVファイルのデータが読み込まれて表示されます(図5)。

図5:Windows Formsアプリの実行結果(起動直後)
図5:Windows Formsアプリの実行結果(起動直後)

 グリッドの最終行に新規レコードを追加したり、既存のレコードのデータを変更したり、行を選択して[削除]ボタンをクリックすることで、グリッドの内容が変化するのを確認してください。最後に[保存]ボタンをクリックすれば、CSVファイルに作業内容が反映されます。CSVファイルをテキストエディタなどで開いて、ファイルも変更されていることを確認してみましょう。

まとめ

 今回は、CSVデータをComponentOne Data Servicesを使って操作するアプリを一括処理に対応させて、Data Servicesが大量のデータの処理にも対応できることを紹介しました。また、Entity Framework連携によるモデル指向のデータ操作を、WinFormsアプリを作成する事例を通じても紹介しました。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ComponentZine(ComponentOne)byメシウス連載記事一覧
この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

提供:メシウス株式会社

【AD】本記事の内容は記事掲載開始時点のものです 企画・制作 株式会社翔泳社

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/22124 2025/10/15 12:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング