【C#】WPF(MVVM)でPostgreSQL内のデータを取得する方法

実行環境

■Windows10
■Visual Studio Community 2019
■WPF(Prism Blank App)
■PostgreSQL 13.1
■pgAdmin4

 

MVVMとは

MVVMはUIを持つアプリケーションに適用されるソフトウェアアーキテクチャ(デザインパターン)の一種です。

MVVMはアプリケーションをModel-View-ViewModelの3要素に分割します。

プレゼンテーション層とドメイン層を分離することにより、アプリケーションの保守性・開発生産性を向上させることができます。

また、MVVMパターンはMVC(Model-View-Controller)パターンの派生です。

 

サンプルコード

表示ボタンを押すと、リストボックスにPostgreSQL内のデータが表示される簡単なアプリケーションを作成します。

 

データベース作成

今回使用するDBはPostgreSQLです。
データベース名がsample2、テーブル名がcustomerになります。

上記のデータを使用していきます。

 

プロジェクト作成

まずは、新しいプロジェクトを作成します。

Prismと入力すると、上記の画面になります。
もし、Prismが入っていない場合は先にPrismを導入してください(ここでは省略します)。

Prism Blank App(WPF)を選択します。
プロジェクト名を入力する画面が出てくるかと思います。
こちらは任意の名前をつけてください。
プロジェクト名と場所を適当に決めたら作成ボタンを押します。

そうすると下記の表示が出てきます。

DrylocかUnityが選べます。
基本的には、Unityで問題ないです。

選択後、下記のような表示ができていればOKです。

開いた直後には、エラーもしくは警告が表示されているかと思います。
こちらは、一度開始ボタンを押すと消えます。

 

NuGetパッケージのインストール

プロジェクト名を右クリックし、NuGetパッケージ管理を開きます。
PostgreSQLとデータのやり取りをするために、NpgsqlとDapperをインストールします(今回はDapperを使用します)。

上記のようになっていれば、OKです。

Prismを使うとViewフォルダとViewModelフォルダが自動で生成されます。
Viewフォルダの中にMainWindow.xamlとMainWindow xaml.cs。
ViewModelフォルダの中にMainWindowViewModel.csがデフォルトで入っています。

MainWindow.xaml.csはコードビハインドと呼ばれるものです。
WinFormsではコードビハインドに処理を書いていました。
しかし、WPFでは基本的にコードビハインド側には何も書きません。

コードビハインド側に処理を書いてしまうと、ViewとViewModelが切り離せなくなりテストがしづらいといったデメリットがあるためです。

 

View

<Window x:Class="sample2.Views.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="350" Width="525"
        WindowStartupLocation="CenterScreen">
    <Grid Margin="10">
        <StackPanel>
            <Button Height="30" Width="300" Margin="0, 30, 0, 30"
                    Content="表示ボタン"
                    Command="{Binding ViewButton1Command}">
            </Button>
            <ListBox Height="100" Width="300"
                 ItemsSource="{Binding Names}">
            </ListBox>
        </StackPanel>

        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>

下記のようになっていれば、OKです。

 

ViewModel

using Prism.Commands;
using Prism.Mvvm;
using System.Collections.ObjectModel;

namespace sample2.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

     // コンストラクタ内でDelegateCommandのインスタンスを生成
        public MainWindowViewModel()
        {
            ViewButton1Command = new DelegateCommand(ViewButton1CommandExecute);
        }

        // Command作成
        public DelegateCommand ViewButton1Command { get; }

        // 表示ボタンが押された際の処理
        public void ViewButton1CommandExecute()
        {
            _names.Add("ここにDBのデータを入れる");
        }

        // Listみたいなもの(データを入れておく箱)
        ObservableCollection _names = new ObservableCollection();

        public ObservableCollection Names
        {
            get { return _names; }
            set { SetProperty(ref _names, value); }
        }
    }
}

ここまでで実行。

表示ボタンを押すと、下記の内容がリストボックスに表示されます。

// 表示ボタンが押された際の処理
public void ViewButton1CommandExecute()
{ 
  _names.Add("ここにDBのデータを入れる");
}

こちらに、PostgreSQLから取得したデータを追加していきます。

 

Model

Modelのフォルダを作成します。

プロジェクト名を右クリック(下記の画像ではsample2)→ 追加をクリック → 新しいフォルダーをクリック。
Modelという名前のフォルダを作成します。


上記のようになっていれば、OKです。

 

Entity(Model)

次に、PostgreSQLから取得してきたデータが入る入れ物を作ります(Entity)。

Modelフォルダを右クリック → 追加をクリック → 新しいフォルダーをクリック。
Entitiesという名前のフォルダを作成します。

Entitiesフォルダの中に、NameEntityというクラスを作ります。
Entitiesフォルダを右クリック → 追加 → クラスをクリック。
クラス名を「NameEntity」とします。


追加ボタンを押下します。
これでデータを格納するクラスが完成です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sample2.Model.Entities
{
   // アクセス修飾子をpublic、sealedで継承できないようにしています。
    public sealed class NameEntity
    {
        // コンストラクタ
        public NameEntity(string name)
        {
            Name = name;
        }

     // プロパティ
        public string Name { get; }

    }
}

 

DBConnection(Model)

PostgreSQLへ接続するためのクラスを作成します。

手順はNameEntityクラスを作成した時と同じです。

Modelフォルダの配下にDaoフォルダを作成。


Daoフォルダの中に「DBConnection」クラスを作成。


こちらが、PostgreSQLとのやり取りを行うためのクラスになります。

using Dapper;
using Npgsql;
using sample2.Model.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sample2.Model.Dao
{
   // アクセス修飾子をpublic、staticで静的クラスに
   public static class DBConnection
   {
    // 接続文字列をprivateな静的メンバ変数でもつ
    private static string _connectionString;
       
    // コンストラクタで接続文字列を作成
    static DBConnection()
    {
      var builder = new NpgsqlConnectionStringBuilder();
      // ホスト
      builder.Host = "localhost";

      // ポート番号
      builder.Port = 5432;

          // データベース名
          builder.Database = "sample2";

          // ユーザー名
          builder.Username = "ユーザー名";

          // パスワード
          builder.Password = "パスワード";

          builder.Timeout = 60;
          builder.CommandTimeout = 60;

          // private変数の_connectionStringに代入
          _connectionString = builder.ToString();
        } 

       /* Dapperでcustomerテーブルのnameカラムを取得するメソッド
          戻り値をListでNameEntityクラス型にしています */
    public static List GetName()
    {
          // SELECT文でcustomerクラスのnameカラムを取得
         var sql = @"SELECT name FROM customer";
          // コネクション(引数に接続文字列の_connectionStringを入れます)
      using (var connection = new NpgsqlConnection(_connectionString))
      {
           return connection.Query(sql).ToList();
      }
    }
  }
}

これでDBConnectionクラスは完成です。

 

ViewModelで表示ボタンを押下した際の処理(ViewModel)

最後にボタンを押下した際の処理を記述します。

// 表示ボタンが押された際の処理
public void ViewButton1CommandExecute()
{
   // GetNameメソッドを実行して変数resultに代入(staticなクラスなのでnewはしない)
   var result = DBConnection.GetName();

   foreach (var val in result)
   {
    _names.Add(val.Name);
   }
}

これですべて完成です。

 

実行結果


表示ボタンを押下すると、データベース名(sample2)のテーブル名(cutomer)内のnameカラムのデータを表示することができます。

 

おすすめ・参考書籍

■C#を学習し始めた方向け
やさしいC 第3版 (「やさしい」シリーズ)

1週間でCの基礎が学べる本

確かな力が身につくC「超」入門 第2版 (Informatics&IDEA)

■C#をある程度学習した方向け
基礎からしっかり学ぶCの教科書 改訂新版 (マイクロソフト関連書)

独習C 新版

Effective C 6.0/7.0