おはようございます。
今回は、PostgreSQLを使ってデータを検索、データグリッドに表示してみます。
お決まりですが、プログラムは前回までのものを流用します。
【WPF】ProgressRingを使って時間のかかる処理を分かりやすくする
また、PostgreSQLをインストールしていない場合は次の記事を参照して、パソコンにインストールしてください。
PostgreSQL 9.6.3 をインストールしてテーブルを作成する
ソリューションエクスプローラーからプロジェクトを選択、右クリックし
「Nuget パッケージの管理」を選択
Nuget パッケージ管理画面が表示されるので、
検索窓に「Npgsql 6」を入力し、「EntityFramework6.Npgsql」を選択、
インストールボタンをクリックします。
プレビュー画面が表示される場合は「OK」ボタンをクリックします。
出力ビューに「終了」が表示されれば完了です。
PostgreSQL ではスキーマ単位の管理をしておかないと困ることになります。
スキーマ指定しないでテーブル作成すると「public」スキーマに作成されるのですが、
C#からの接続時には必ず(やってみた限りでは)スキーマ指定しないといけないので、まずはスキーマを作成しておきます。
CREATE SCHEMA dora;
作成したスキーマににテーブルを作成
SQLite の時と同じテーブル、データを用意します。
このとき、テーブル名やカラム名は小文字にしておくこと。
CREATE TABLE IF NOT EXISTS dora.mstkind (
kind_cd CHAR(2) NOT NULL
, kind_name VARCHAR(20)
, primary key (kind_cd)
);
CREATE TABLE IF NOT EXISTS dora.tblcat (
no INTEGER NOT NULL
, name VARCHAR(20) NOT NULL
, sex CHAR(3) NOT NULL
, age INTEGER DEFAULT 0 NOT NULL
, kind_cd CHAR(2) DEFAULT '00' NOT NULL
, favorite VARCHAR(40)
, PRIMARY KEY (no)
);
INSERT INTO DORA.MSTKIND VALUES ('01', 'キジトラ');
INSERT INTO DORA.MSTKIND VALUES ('02', '長毛種(不明)');
INSERT INTO DORA.MSTKIND VALUES ('03', 'ミケ(っぽい)');
INSERT INTO DORA.MSTKIND VALUES ('04', 'サビ');
INSERT INTO DORA.MSTKIND VALUES ('09', 'その他');
INSERT INTO DORA.TBLCAT VALUES('1','そら','♂','6','01','犬の人形');
INSERT INTO DORA.TBLCAT VALUES('2','りく','♂','5','02','人間');
INSERT INTO DORA.TBLCAT VALUES('3','うみ','♀','4','03','高級ウェットフード');
INSERT INTO DORA.TBLCAT VALUES('4','こうめ','♀','2','04','横取りフード');
次のようにします。
重要な部分は、「entityFramework」タグと「system.data」タグ。
App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v13.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Npgsql" />
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql" type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories>
</system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Npgsql" publicKeyToken="5d8b90d52f46fda7" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.2.5.0" newVersion="3.2.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
DbContextを継承したクラスを作成します。
このクラスでデータベースへの接続、Entityへのマッピングなどを行います。
デフォルトのスキーマを変更する場合、「OnModelCreating」メソッドにて設定可能です。
PgDbContext.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using Npgsql;
namespace WpfApp1
{
class PgDbContext : DbContext
{
private const string ConnectionString = "Server=localhost;User ID=USER01;Password=USER01;Database=DB01;port=5432";
// コンストラクタにて接続文字列を設定
public PgDbContext() : base(new NpgsqlConnection(ConnectionString), true) { }
public DbSet<Kind> Kinds { get; set; }
public DbSet<Cat> Cats { get; set; }
// スキーマを変更する場合にはここに設定
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Configure default schema
modelBuilder.HasDefaultSchema("dora");
}
}
}
アノテーションが今までのとちょっと違うので修正します。
Kind.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WpfApp1
{
[Table("mstkind")]
class Kind
{
[Key]
[Column("kind_cd")]
public String KindCd { get; set; }
[Column("kind_name")]
public String KindName { get; set; }
}
}
Cat.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WpfApp1
{
[Table("tblcat")]
class Cat
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Column("no")]
public int No { get; set; }
[Column("name")]
public String Name { get; set; }
[Column("sex")]
public String Sex { get; set; }
[Column("age")]
public int Age { get; set; }
[Column("kind_cd")]
public String Kind { get; set; }
[Column("favorite")]
public String Favorite { get; set; }
}
}
MainWindow.xaml.cs
using Npgsql;
using System.ComponentModel;
テーブル作成以外、全ての箇所を変更します。
MainWindow.xaml.cs
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
using (var context = new PgDbContext())
テーブル作成は今まで通りコマンドで行います。
(また別途、DbContext でのやり方は紹介します)
SQLite とは微妙に違うところ(型、長さ)を変更。
MainWindow.xaml.cs
// テーブルが存在しなければ作成する
// 種別マスタ
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE IF NOT EXISTS mstkind (");
sb.Append(" kind_cd CHAR(2) NOT NULL");
sb.Append(" , kind_name VARCHAR(20)");
sb.Append(" , PRIMARY KEY (kind_cd)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
// 猫テーブル
sb.Clear();
sb.Append("CREATE TABLE IF NOT EXISTS tblcat (");
sb.Append(" no INTEGER NOT NULL");
sb.Append(" , name VARCHAR(20) NOT NULL");
sb.Append(" , sex CHAR(3) NOT NULL");
sb.Append(" , age INTEGER DEFAULT 0 NOT NULL");
sb.Append(" , kind_cd CHAR(2) DEFAULT '00' NOT NULL");
sb.Append(" , favorite VARCHAR(40)");
sb.Append(" , PRIMARY KEY (no)");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
MainWindow.xaml.cs
/// <summary>
/// 検索処理(非同期)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SearchProcess(object sender, DoWorkEventArgs e)
{
// 猫データマスタを取得してコンボボックスに設定する
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
// PgDbContext に変更
using (var context = new PgDbContext())
{
String searchName = this.search_name.Text;
String searchKind = (this.search_kind.SelectedValue as Kind).KindCd;
// データを取得
// context から DbSet を取得
//Table<Cat> tblCat = con.GetTable<Cat>();
var tblCat = context.Cats;
// サンプルなので適当に組み立てる
IQueryable<Cat> result;
if (searchKind == "")
{
// 名前は前方一致のため常に条件していしても問題なし
result = from x in tblCat
where x.Name.StartsWith(searchName)
orderby x.No
select x;
}
else
{
result = from x in tblCat
where x.Name.StartsWith(searchName) & x.Kind == searchKind
orderby x.No
select x;
}
this.dataGrid.ItemsSource = result.ToList();
}
}
データグリッドに表示する際に値を変換している箇所も、DB接続しているため変更します。
KindConverter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Linq;
using System.Data.SQLite;
using System.Data.SQLite.Linq;
// Converter 用
// IValueConverter、CultureInfo
using System.Windows.Data;
using System.Globalization;
namespace WpfApp1
{
/// <summary>
/// 種別コンバータークラス.
/// </summary>
public class KindConverter : IValueConverter
{
/// <summary>
/// データ変換処理
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
// PgDbContext に変更
using (var context = new PgDbContext())
{
// データを取得
//Table<Kind> tblCat = con.GetTable<Kind>();
//Kind k = tblCat.Single(c => c.KindCd == value as String);
var kind = context.Kinds.SingleOrDefault(c => c.KindCd == (String)value);
if (kind != null)
{
return kind.KindName;
}
return "";
}
}
/// <summary>
/// データ復元処理
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
using (var context = new PgDbContext())
{
// データを取得
//Table<Kind> tblCat = con.GetTable<Kind>();
//Kind k = tblCat.Single(c => c.KindCd == value as String);
var kind = context.Kinds.SingleOrDefault(c => c.KindName == value as String);
if (kind != null)
{
return kind.KindCd;
}
}
return "";
}
}
}
無事に起動、検索することができました。
ひとまず、元々の処理(SQLite、MySQL)とあまり変更せずに実装することができました。
ちょっと長くなってしまったので、
登録、更新、削除はまた次回とさせていただきます。
ではでは。
第1回 | 【WPF】PostgreSQL に接続してデータを取得して表示する |
第2回 | 【WPF】PostgreSQL に接続してデータを操作(登録、更新、削除)してみる |
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント