1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

# 【WPF × SQLite】最小構成でデータ登録アプリを作る

Posted at

WPF アプリから SQLite(System.Data.SQLite) を使ってデータを登録(INSERT)する最小構成のサンプルです。
MVVM 構成+DI(依存性注入)+ SQLite の基本を理解するのに最適です。


🎯 目的

  • SQLite データベースにレコードを登録する
  • MVVM パターンで責務を分離
  • System.Data.SQLite を使用(Microsoft.Data.Sqlite ではない)

📂 プロジェクト構成

WpfMinimalMvvm/
├── Models/
│   └── Employee.cs
├── IServices/
│   └── IEmployeeRepository.cs
├── Services/
│   └── SqliteEmployeeRepository.cs
├── ViewModels/
│   └── MainViewModel.cs
└── MainWindow.xaml
└── MainWindow.xaml.cs
└── App.xaml / App.xaml.cs

🧱 Models/Employee.cs

namespace WpfMinimalMvvm.Models
{
    public class Employee
    {
        public int Id { get; set; }          // 自動採番
        public string Name { get; set; } = ""; // 必須
        public int Age { get; set; }         // 例:年齢
        public bool IsActive { get; set; }   // 例:在籍
    }
}

🧩 IServices/IEmployeeRepository.cs

using System.Threading.Tasks;
using WpfMinimalMvvm.Models;

namespace WpfMinimalMvvm.IServices
{
    public interface IEmployeeRepository
    {
        Task<int> InsertAsync(Employee employee);
    }
}

⚙️ Services/SqliteEmployeeRepository.cs

using System.Data.SQLite;
using System.IO;
using WpfMinimalMvvm.IServices;
using WpfMinimalMvvm.Models;

namespace WpfMinimalMvvm.Services
{
    public class SqliteEmployeeRepository : IEmployeeRepository
    {
        private readonly string _dbPath;

        public SqliteEmployeeRepository()
        {
            // コメント:実行フォルダに app.db を作成
            _dbPath = Path.Combine(Directory.GetCurrentDirectory(), "app.db");

            // コメント:初回のみテーブル作成
            using (var cn = new SQLiteConnection($"Data Source={_dbPath};Version=3;"))
            {
                cn.Open();
                using (var cmd = cn.CreateCommand())
                {
                    cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS Employees(
  Id       INTEGER PRIMARY KEY AUTOINCREMENT,
  Name     TEXT    NOT NULL,
  Age      INTEGER NOT NULL,
  IsActive INTEGER NOT NULL
);";
                    cmd.ExecuteNonQuery();
                }
            }
        }

        public async Task<int> InsertAsync(Employee employee)
        {
            // コメント:必ず {} を使うスタイル。Name は必須
            if (string.IsNullOrWhiteSpace(employee.Name))
            {
                throw new System.ArgumentException("Name は必須です。");
            }

            using (var cn = new SQLiteConnection($"Data Source={_dbPath};Version=3;"))
            {
                await cn.OpenAsync();

                using (var cmd = cn.CreateCommand())
                {
                    cmd.CommandText = @"
INSERT INTO Employees (Name, Age, IsActive)
VALUES (@name, @age, @active);
SELECT last_insert_rowid();
";
                    cmd.Parameters.AddWithValue("@name", employee.Name);
                    cmd.Parameters.AddWithValue("@age", employee.Age);
                    cmd.Parameters.AddWithValue("@active", employee.IsActive ? 1 : 0);

                    var idObj = await cmd.ExecuteScalarAsync();
                    return System.Convert.ToInt32(idObj);
                }
            }
        }
    }
}


🧭 ViewModels/MainViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using WpfMinimalMvvm.IServices;
using WpfMinimalMvvm.Models;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Xml.Linq;

namespace WpfMinimalMvvm.ViewModels
{
    public partial class MainViewModel : ObservableObject
    {
        private readonly IEmployeeRepository _repo;

        public MainViewModel(IEmployeeRepository repo)
        {
            _repo = repo;
        }

        // 入力項目
        [ObservableProperty]
        private string name = "";

        [ObservableProperty]
        private int age = 20;

        [ObservableProperty]
        private bool isActive = true;

        // 結果表示用
        [ObservableProperty]
        private string message = "準備OK";

        // 追加ボタン
        [RelayCommand]
        private async Task SaveAsync()
        {
            // 簡易バリデーション
            if (string.IsNullOrWhiteSpace(Name))
            {
                Message = "Name を入力してください。";
                return;
            }

            Employee emp = new Employee
            {
                Name = Name,
                Age = Age,
                IsActive = IsActive
            };

            // DBへ登録
            int newId = await _repo.InsertAsync(emp);
            Message = $"登録しました(Id={newId})";
        }
    }
}

🪟 MainWindow.xaml

<Window x:Class="WpfMinimalMvvm.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SQLite Insert Sample" Height="220" Width="360">
    <Grid Margin="16">
        <StackPanel>
            <TextBlock Text="Name" />
            <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />

            <TextBlock Text="Age" Margin="0,8,0,0"/>
            <TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" />

            <CheckBox Content="Is Active" IsChecked="{Binding IsActive}" Margin="0,8,0,0"/>

            <Button Content="登録" Command="{Binding SaveCommand}" Margin="0,8,0,0"/>

            <TextBlock Text="{Binding Message}" FontSize="14" Margin="0,8,0,0"/>
        </StackPanel>
    </Grid>
</Window>

🧱 MainWindow.xaml.cs

using System.Text;
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;
using WpfMinimalMvvm.ViewModels;

namespace WpfMinimalMvvm
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow(MainViewModel vm)
        {
            InitializeComponent();
            DataContext = vm;
        }
    }
}


🚀 App.xaml.cs

using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using WpfMinimalMvvm.IServices;   // ← IEmployeeRepository
using WpfMinimalMvvm.Services;    // ← SqliteEmployeeRepository
using WpfMinimalMvvm.ViewModels;  // ← MainViewModel

namespace WpfMinimalMvvm
{
    public partial class App : Application
    {
        private ServiceProvider? _provider;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            var services = new ServiceCollection();

            // コメント:SQLiteリポジトリ(Singletonで共有)
            services.AddSingleton<IEmployeeRepository, SqliteEmployeeRepository>();

            // コメント:ViewModel / View は通常どおり
            services.AddTransient<MainViewModel>();
            services.AddTransient<MainWindow>();

            _provider = services.BuildServiceProvider();

            var window = _provider.GetRequiredService<MainWindow>();
            window.Show();
        }
    }
}


✅ SQLite 確認コマンド

cd bin\Debug
et8.0-windows
sqlite3 app.db
.tables
.headers on
.mode column
SELECT * FROM Employees;

⚙️ 使用パッケージ

パッケージ名 用途
System.Data.SQLite.Core SQLite ADO.NETプロバイダ
CommunityToolkit.Mvvm MVVM用ヘルパ
Microsoft.Extensions.DependencyInjection DIコンテナ

📘 これで WPF + SQLite の登録機能が完成!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?