【WPF】SQLite から Linq でデータを取得してDataGrid に表示してみる

2017年6月9日C#,開発

おはようございます。

今日も引き続き WPF@C#の話しです。

その他リソースの外部ファイル化をやろうかと思ったのですが、
DataGridにちゃんとデータベースからデータを表示したかったのでちょっと寄り道。

とりあえずサンプルなんかで無料のデータベースを使うのあれば SQLite で十分なので、
SQLiteを使ってデータの検索、DataGridへの表示をやってみようと思います。

プログラムは前回のものを修正します。

まずは SQLite に接続するための準備から。

スポンサーリンク

Nuget でパッケージをダウンロード

プロジェクトのコンテキストメニュー

ソリューションエクスプローラーからプロジェクトを選択、右クリックし
「Nuget パッケージの管理」を選択します。

Nuget パッケージ管理画面

Nuget パッケージ管理画面が表示されるので、
検索窓に「SQLite」を入力し、「System.Data.SQLite」を選択、
インストールボタンをクリックします。

変更確認画面

変更の確認ダイアログが表示されるので、
「OK」ボタンをクリックします。

出力ビュー

出力ビューに「終了」が出力されればOKです。

参照の確認

ソリューションエクスプローラーの「参照」を開き
System.Data.* が追加されていることが確認できれば追加完了です。

ビルド

一度ビルドを実行します。
上部メニューの「ビルド」>「ソリューションのリビルド」を選択します。

エクスプローラ

プロジェクトのディレクトリ>bin>Target>x86 、x64 に「SQLite.Interop.dll」が
出力されていることを確認します。

起動時にテーブルを作成する

プログラム修正

アプリケーション起動時に、テーブルを作成するようにプログラムを修正します。

MainWindows.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    // SQLite利用のため追加
    using System.Data.SQLite;
    
    namespace WpfApp1
    {
        /// <summary>
        /// MainWindow.xaml の相互作用ロジック
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                // SampleDb.sqlite を作成(存在しなければ)
                using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
                {
                    // データベースに接続
                    conn.Open();
                    // コマンドの実行
                    using (var command = conn.CreateCommand())
                    {
                        // テーブルが存在しなければ作成する
                        // 種別マスタ
                        StringBuilder sb = new StringBuilder();
                        sb.Append("CREATE TABLE IF NOT EXISTS MSTKIND (");
                        sb.Append("  KIND_CD NCHAR NOT NULL");
                        sb.Append("  , KIND_NAME NVARCHAR");
                        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 INT NOT NULL");
                        sb.Append("  , NAME NVARCHAR NOT NULL");
                        sb.Append("  , SEX NVARCHAR NOT NULL");
                        sb.Append("  , AGE INT DEFAULT 0 NOT NULL");
                        sb.Append("  , KIND_CD NCHAR DEFAULT 0 NOT NULL");
                        sb.Append("  , FAVORITE NVARCHAR");
                        sb.Append("  , primary key (NO)");
                        sb.Append(")");
    
                        command.CommandText = sb.ToString();
                        command.ExecuteNonQuery();
    
                    }
                    // 切断
                    conn.Close();
                }
            }
        }
    }

 

アプリケーションの実行

上部メニューの開始ボタンをクリックし、アプリケーションを実行すると
「MSTKIND」、「TBLCAT」テーブルが作成されます。

SQLite Manager

SQLite のデータベースを操作できるツール等で、テーブルが作成されていることを確認します。

今回は Firefox のアドオン「SQLite Manager」で確認しました。

データの追加

次のデータをツール、もしくはコマンドラインから追加します。

    INSERT INTO MSTKIND VALUES ("01", "キジトラ");
    INSERT INTO MSTKIND VALUES ("02", "長毛種(不明)");
    INSERT INTO MSTKIND VALUES ("03", "ミケ(っぽい)");
    INSERT INTO MSTKIND VALUES ("04", "サビ");
    INSERT INTO MSTKIND VALUES ("09", "その他");
    INSERT INTO TBLCAT VALUES('1','そら','♂','6','01','犬の人形');
    INSERT INTO TBLCAT VALUES('2','りく','♂','5','02','人間');
    INSERT INTO TBLCAT VALUES('3','うみ','♀','4','03','高級ウェットフード');
    INSERT INTO TBLCAT VALUES('4','こうめ','♀','2','04','横取りフード');

今度はコマンドラインから追加してみました。

SQLite Manager

更に SQLite Manager にて確認。

Linq で データを取得、設定する

Linqとは

オブジェクトやデータベース、データセット、エンティティ、XML文書など、アプリケーションで扱うさまざまなデータソースに対して、統一的な手段でアクセスするしくみ

Linq用パッケージの追加

Linqを利用するため、ライブラリの追加を行います。

ソリューションエクスプローラに表示されている「参照」を右クリックし
参照の追加画面を開きます。

参照の追加

「System.Data.Linq」を検索し、表示されたものを選択、「OK」ボタンをクリックします。

プログラム修正

クラス追加

種別クラス

Kind.cs

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

using System.Data.Linq.Mapping;

namespace WpfApp1
{
    [Table(Name = "mstkind")]
    public class Kind
    {
        [Column(Name = "kind_cd", IsPrimaryKey = true)]
        public String KindCd { get; set; }
        [Column(Name = "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.Data.Linq.Mapping;

namespace WpfApp1
{
    [Table(Name = "tblcat")]
    public class Cat
    {

        [Column(Name = "no", IsPrimaryKey = true)]
        public int No { get; set; }
        [Column(Name = "name")]
        public String Name { get; set; }
        [Column(Name = "sex")]
        public String Sex { get; set; }
        [Column(Name = "age")]
        public int Age { get; set; }
        [Column(Name = "kind_cd")]
        public String Kind { get; set; }
        [Column(Name = "favorite")]
        public String Favorite { get; set; }
    }
}

 

宣言の追加

MainWindow.xaml.cs

Linqを利用するためにパッケージ利用宣言を追加
(System.Data.Linq.Mapping)

省略
.
.

using System.Data.SQLite; 

using System.Data.Linq; // ←を追記する
using System.Data.Linq.Mapping; // ←を追記する

namespace WpfApp1 {
省略
}

データ取得処理の追加

「MainWindow」メソッドに次の記述を追加

MainWindow.xaml.cs

                    // 種別マスタを取得してコンボボックスに設定する
                    using (DataContext con = new DataContext(conn))
                    {
                        // データを取得
                        Table<Kind> mstKind = con.GetTable<Kind>();
                        IQueryable<Kind> result = from x in mstKind orderby x.KindCd select x;
    
                        // 最初の要素は「指定なし」とする
                        Kind empty = new Kind();
                        empty.KindCd = "";
                        empty.KindName = "指定なし";
                        var list = result.ToList();
                        list.Insert(0, empty);
    
                        // コンボボックスに設定
                        this.search_kind.ItemsSource = list;
                        this.search_kind.DisplayMemberPath = "KindName";
                    }

新規メソッドの追加(クリックイベント)

            /// <summary>
            /// 検索ボタンクリックイベント.
            /// 
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void search_button_Click(object sender, RoutedEventArgs e)
            {
                using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))
                {
                    conn.Open();
    
                    // 猫データ一覧を取得して DataGrid に設定
                    using (DataContext con = new DataContext(conn))
                    {
                        String searchName = this.search_name.Text;
                        String searchKind = (this.search_kind.SelectedValue as Kind).KindCd;
    
                        // データを取得
                        Table<Cat> tblCat = con.GetTable<Cat>();
    
                        // サンプルなので適当に組み立てる
                        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();
                    }
    
                    conn.Close();
                }
    
            }

ビューの修正

検索ボタンにクリックイベントを追加します。

MainWindows.xaml

    <Button x:Name="search_button" Content="検索" Margin="432,12,0,0" Style="{StaticResource btn-normal}" Click="search_button_Click"/>

起動

修正後画面

全件検索

全件検索

全データが表示されました。

名前指定検索

名前指定検索

名前を指定したので、そらのみ表示されました。

種別指定検索

種別指定検索

みけっぽい、「うみ」のみ表示されました。

存在しない組み合わせで検索

存在しない組み合わせ

こうめはサビなので、なにも表示されません。

まとめ

ひとまず、DataGrid に表示できました。
サンプルなのでソースはまあまあ適当ですが、なんとなく使い方がわかってきました。
(実は Linq も初)

日々新しい技術が出てくるのでついていくのが大変ですね。
頑張ります。

次回(未定)は Log4net を使ってみたいと思います。

ではでは。

ソースはこちら

GitHub

スポンサーリンク


関連するコンテンツ

2017年6月9日C#,開発C#,SQLite,WPF,プログラミング

Posted by doradora