C#WPFの道#9!SQLiteの使い方をわかりやすく解説!

当サイトではアフィリエイト広告を利用しています。

WPF

SQLiteとは?

SQLiteとはフリーで提供されている軽量なデータベースツールです。通常OracleやSQLServerであれば、ソフトのインストールや設定が多くあり、バックアップをとるのも結構大変ですが、SQLiteは1ファイルで完結しているため、バックアップをとるにしても、普通にファイルをコピーするだけで完結します。最近ではスマホアプリを作成する場合に、スマホ端末自体にデータを保存したい場合などに適しています。また、デスクトップアプリでも、自分の端末でのみ使うような小規模なデータベースとして使うのに適しています。

今回のようなアプリケーションの勉強用に使うデータベースとしては、大変適しているといえます。

SQLiteの導入

SQLiteをWPFで使用するには、WPFのプロジェクトにNuGetでSQLiteをインストールする必要があります。

プロジェクトの「参照」を右クリックして

NuGetパッケージの管理を選択します。

NuGetマネージャーの「参照」を選択し、検索窓に「sqlite-net」と入力します。

Sqlite-net-pclを選択し、バージョンが最新の安定版に選択されていることを確認して「インストール」ボタンを押下し、インストールを行います。

WPFの画面の作成

それではSQLiteのデータ登録とデータ取得のプログラムを作成していきます。はじめに、WPFの画面を作成します。今回は顧客管理システムの一部を作成する想定で行うので、顧客の名前と電話番号を登録する画面を作成します。WPFプロジェクトを作成したときに自動で生成されるMainWindow.xamlのXaml入力エリアに次のように定義します。StackPanelにテキストボックスを2個、ボタンを1個置きます。テキストボックスはそれぞれ顧客の名前と電話番号の入力エリアです。ボタンはSaveボタンです。このボタンを押下すると、SQLiteのCustomerテーブルにデータを登録する仕様とします。

<Window x:Class="WPF009.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF009"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <StackPanel Margin="10">
            <TextBox x:Name="NameTextBox"/>
            <TextBox x:Name="PhoneTextBox"/>
            <Button Content="Save"
                    x:Name="SaveButton"
                    Click="SaveButton_Click"/>
        </StackPanel>
    </Grid>
</Window>

コードファーストによるSQLiteの操作

今回はSQLiteの操作はすべてコードファーストで行います。コードファーストとは、通常データベースには、テーブルの定義と作成等を行ってから、C#からデータの登録処理等を行いますが、コードファーストでは、テーブルの定義、テーブルの作成、データの作成、データ検索のすべてをC#のプログラムコードで行います。

テーブルとなるクラスを作成

コードファーストで作成するため、SQLiteのテーブルに定義をC#のクラスとして作成します。今回は顧客管理システムの一部を作成するサンプルとして、顧客テーブルにあたる「Customer」クラスを作成します。

WPFのプロジェクトに新規のフォルダーを追加し、「Objects」フォルダーとします。その中に、Customerクラスを作成します。

using SQLite;

namespace WPF009.Objects
{
    public class Customer
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }

        /// <summary>
        /// 名前
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 電話番号
        /// </summary>
        public string Phone { get; set; }
    }
}

Customerクラスに顧客の名前と電話番号を格納するstringのプロパティを作成します。最初のintのIdは画面レイアウトには存在していませんでしたが、Customerテーブルのプライマリキーとして定義しています。プライマリキーとは、そのテーブルの中に重複した値が存在しない列という意味です。これでCustomerテーブルにIdの重複したデータは存在できないという定義をしたことになります。AutoIncrementの定義は、オードナンバーの定義です。データが登録されるたびに、1から順番の連番が自動的にIdとして割り当てられます。これでCustomerクラスの定義は完了です。

Saveボタンクリックイベント

Saveボタンをクリックしたときに、SQLiteに画面の顧客名と電話番号を登録するプログラムを記述していきます。

using SQLite;
using System;
using System.Windows;
using WPF009.Objects;

namespace WPF009
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            var customer = new Customer()
            {
                Name = NameTextBox.Text,
                Phone = PhoneTextBox.Text,
            };

            string databaseName = "Shop.db";
            string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string databasePath = System.IO.Path.Combine(folderPath, databaseName);
            using (var connection = new SQLiteConnection(databasePath))
            {
                connection.CreateTable<Customer>();
                connection.Insert(customer);
            }
        }
    }
}

まず、var customer = new Customer()のところで、Cusutomerクラスを生成し、画面の顧客名と電話番号を設定しています。

その後のdatabaseNameはデータベースの名前です。任意の名前でいいので今回はShop.dbとしています。folderPathはデータベースファイルの場所です。今回はコードファーストでデータベースを作成するため、まだデータベースファイルは存在しません。後述のconnection.CreateTableを最初に実行したときに自動生成されるので、任意の場所を指定します。今回はEnvironment.SpecialFolder.MyDocumentsで、自分のPCのマイドキュメントを指定しています。

SQLiteConnectionでSQLiteと接続します。このクラスを使用するためにクラスに最初に記述するusingにSQLiteを追加します。SQLiteConnectionを生成するためには、データベースのパスが必要になります。前述したdatabasePathを指定します。

ちなみにSQLiteConnectionはDisopose()メソッドが存在することからもわかるようにIDisposableインタフェースが定義されています。クラス生成後はメモリの解放が必要なためDisopose()、もしくはClose()を呼び出す必要があります。しかし今回はメソッド内で

SQLiteConnectionの使用が完結するためusingキーワードを使って解放処理を行っています。

「connection.CreateTable<Customer>();」をすることで、データベースや、Cusutomerテーブルが存在しない場合でもエラーにならず、空のテーブルを作成してくれます。存在している場合は何もしないため、このコードを記述しておくことで、初回もエラーにならずに、テーブルが自動生成されます。

「connection.Insert(customer);」で実際にCustomerテーブルにcustomerインスタンスの値がインサートされます。

登録処理は以上です。ただ、これだけだと、実際に登録されたのかを確認できないため、データを取得する処理を、続けて作成していきます。

データの取得処理

MainWindow.xamlにReadButtonを追加し、Clickイベントを作成します。

<Window x:Class="WPF009.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF009"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="300">
    <Grid>
        <StackPanel Margin="10">
            <TextBox x:Name="NameTextBox"/>
            <TextBox x:Name="PhoneTextBox"/>
            <Button Content="Save"
                    x:Name="SaveButton"
                    Click="SaveButton_Click"/>
            <Button Content="Read"
                    x:Name="ReadButton"
                    Click="ReadButton_Click"/>
        </StackPanel>
    </Grid>
</Window>

データベースの接続先は各画面から参照する必要があるためApp.xamlのコードビハインド側にデータベースパスの設定を移動し、共通で使えるように変更しました。

using System;
using System.Windows;

namespace WPF009
{
    /// <summary>
    /// App.xaml の相互作用ロジック
    /// </summary>
    public partial class App : Application
    {
        static string databaseName = "Shop.db";
        static string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        public static string DatabasePath = System.IO.Path.Combine(folderPath, databaseName);
    }
}

コードビハインド側にReadButton_Clickを追加

using SQLite;
using System;
using System.Windows;
using WPF009.Objects;

namespace WPF009
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
     
        public MainWindow()
        {
            InitializeComponent();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            var customer = new Customer()
            {
                Name = NameTextBox.Text,
                Phone = PhoneTextBox.Text,
            };

            using (var connection = new SQLiteConnection(App.DatabasePath))
            {
                connection.CreateTable<Customer>();
                connection.Insert(customer);
            }
        }

        private void ReadButton_Click(object sender, RoutedEventArgs e)
        {
            using (var connection = new SQLiteConnection(App.DatabasePath))
            {
                connection.CreateTable<Customer>();
                var customers = connection.Table<Customer>().ToList();
            }
        }
    }
}

Saveクリックのときと同じようにSQLiteConnectionを生成しテーブルがないときのためにCreateTableを実行しています。 「var customers = connection.Table().ToList();」でSQLiteのCustomerテーブルから全件を取得し、Customerクラスのリストを取得してcustomersに代入しています。ブレークポイントを設置して、ウォッチで中を見れば、Saveで保存したデータが確認できます。またIdには、連番が設定されていることも確認してください。