C# と MySQL で簡易的な TODO リストを作成しました。
最近 C# を勉強し始めたばかりなので、内容に不備などあるかもしれませんがご了承ください。
バージョン
- MySQL 9.0.1
- Visual Studio 2022
- C# 12.0
- .NET 8.0.10
MySQL の準備
勉強用でちょっと動かすだけなので docker で簡単に用意する。
docker-compose.yml
version: "3"
services:
db:
image: mysql
container_name: mysql
environment:
# 設定必須、rootパスワード
- MYSQL_ROOT_PASSWORD=root
# この設定はオプション、イメージの起動時に作成されるデータベース名
- MYSQL_DATABASE=sample
ports:
- 3306:3306
volumes:
- mysql_data:/var/lib/mysql
phpmyadmin:
container_name: phpmyadmin
image: phpmyadmin/phpmyadmin
environment:
- PMA_ARBITRARY=1
- PMA_HOST=mysql
- PMA_USER=root
- PMA_PASSWORD=root
ports:
- 8080:80
depends_on:
- db
volumes:
mysql_data:
docker-compose.yml
があるフォルダで docker-compose up
を実行すると、
http://localhost:8080/ で phpmyadmin から MySQL に接続できているので、データベース sample にテーブルを作成する。
CREATE TABLE `sample`.`todos` (
`id` int NOT NULL AUTO_INCREMENT,
`todo` text NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`)
);
Visual Studio でプロジェクト作成
Visual Studio の画面から DataGridView を配置する。
MySql.Data を NuGet パッケージ管理から入れる。
MySql.Data をラップして少し使いやすくしたクラスを作成する。
Db.cs
using MySql.Data.MySqlClient;
namespace TodoList
{
internal class Db
{
private static MySqlConnection? _connection;
private static MySqlConnection GetConnection()
{
if (_connection == null)
{
_connection = new MySqlConnection("server=127.0.0.1;uid=root;pwd=root;database=sample");
_connection.Open();
}
return _connection;
}
public static void Execute(string sql, object?[]? param = null)
{
var command = new MySqlCommand(sql, GetConnection());
Array.ForEach(param ?? [], p => command.Parameters.Add(new MySqlParameter("", p)));
command.ExecuteNonQuery();
}
public static string[][] ExecuteAndFetchAll(string sql, object?[]? param = null)
{
var lines = new List<string[]>();
var command = new MySqlCommand(sql, GetConnection());
Array.ForEach(param ?? [], p => command.Parameters.Add(new MySqlParameter("", p)));
using var reader = command.ExecuteReader();
while (reader.Read())
{
string[] line = new string[reader.FieldCount];
for (int i = 0; i < reader.FieldCount; i++)
{
line[i] = reader.GetValue(i)?.ToString() ?? "";
}
lines.Add(line);
}
return lines.ToArray();
}
}
}
Form1 のコードで Todo リストを作る。
Form1.cs
using System.Data;
namespace TodoList
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitGrid();
}
private void InitGrid()
{
dataGridView1.DataSource = makeGridView();
// 変更できないカラムを設定する
foreach (int key in new List<int> { 0, 2, 3 })
{
dataGridView1.Columns[key].ReadOnly = true;
dataGridView1.Columns[key].DefaultCellStyle.BackColor = Color.LightGray;
}
// "更新する"ボタンの列を追加
var updeatColumn = new DataGridViewButtonColumn();
updeatColumn.Name = "更新";
updeatColumn.UseColumnTextForButtonValue = true;
updeatColumn.Text = "更新する";
dataGridView1.Columns.Add(updeatColumn);
// "削除する"ボタンの列を追加
var delColumn = new DataGridViewButtonColumn();
delColumn.Name = "削除";
delColumn.UseColumnTextForButtonValue = true;
delColumn.Text = "削除する";
dataGridView1.Columns.Add(delColumn);
// データがない一番下の行にも"更新する"ボタンを表示する
Action drawBtnText = () => dataGridView1.Rows[dataGridView1.Rows.Count - 1].Cells["更新"].Value = "更新する";
dataGridView1.RowsAdded += (object? sender, DataGridViewRowsAddedEventArgs e) => drawBtnText();
// データ更新イベント設定
dataGridView1.CellContentClick += upsert;
dataGridView1.CellContentClick += delete;
}
private DataTable makeGridView()
{
var dataTable = new DataTable();
dataTable.TableName = "Todos";
dataTable.Columns.Add("id");
dataTable.Columns.Add("内容");
dataTable.Columns.Add("作成日");
dataTable.Columns.Add("更新日");
var todos = Db.ExecuteAndFetchAll("SELECT * FROM todos");
foreach (string[] row in todos)
{
dataTable.Rows.Add(row);
}
return dataTable;
}
private void upsert(object? sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != dataGridView1.Columns["更新"].Index || e.RowIndex == -1)
{
// 更新ボタンを押してない場合は何もしない
return;
}
var isNewRow = false;
if (!int.TryParse(dataGridView1.Rows[e.RowIndex].Cells["id"].Value?.ToString(), out var id))
{
// id が取得できない場合は新規レコード作成する
isNewRow = true;
}
var todoTxt = dataGridView1.Rows[e.RowIndex].Cells["内容"].Value?.ToString();
if (string.IsNullOrEmpty(todoTxt))
{
MessageBox.Show("内容を設定してください");
return;
}
if (isNewRow == true)
{
Db.Execute("INSERT INTO todos (todo, created_at, updated_at) VALUES (?, ?, ?)", [todoTxt, DateTime.Now, DateTime.Now]);
}
else
{
Db.Execute("UPDATE todos SET todo = ?, updated_at = ? WHERE id = ?", [todoTxt, DateTime.Now, id]);
}
dataGridView1.DataSource = makeGridView();
}
private void delete(object? sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != dataGridView1.Columns["削除"].Index || e.RowIndex == -1)
{
// 削除ボタンを押してない場合は何もしない
return;
}
if (!int.TryParse(dataGridView1.Rows[e.RowIndex].Cells["id"].Value?.ToString(), out var id))
{
MessageBox.Show("id が取得できません");
return;
}
Db.Execute("DELETE FROM todos WHERE id = ?", [id]);
dataGridView1.DataSource = makeGridView();
}
}
}
簡単に Todo リストを作成できました。
参考