diff --git a/src/KitsuneCommand/Services/BackupService.cs b/src/KitsuneCommand/Services/BackupService.cs
index f227c3b..0acf263 100644
--- a/src/KitsuneCommand/Services/BackupService.cs
+++ b/src/KitsuneCommand/Services/BackupService.cs
@@ -13,6 +13,15 @@ namespace KitsuneCommand.Services
///
/// Manages world save backups: create, restore, delete, and schedule auto-backups.
/// Stores backup metadata in SQLite for the management UI.
+ ///
+ /// Connection lifetime note:
+ /// returns an *already-opened* connection. Do NOT call conn.Open() again
+ /// inside the using block. The custom-built System.Data.SQLite that ships with
+ /// this mod silently drops subsequent INSERT/UPDATE statements when Open is
+ /// invoked twice — no exception is thrown, the controller returns 200, but no
+ /// row ends up in the table. (Reads happen to keep working, which is why the
+ /// bug went unnoticed long enough to ship a UI for the feature.) Always trust
+ /// the factory to return a ready-to-use connection.
///
public class BackupService
{
@@ -105,7 +114,6 @@ public BackupRecord CreateBackup(string backupType = "manual", string notes = nu
// Save to database
using (var conn = _db.CreateConnection())
{
- conn.Open();
Dapper.SqlMapper.Execute(conn,
@"INSERT INTO backups (filename, world_name, size_bytes, created_at, backup_type, notes)
VALUES (@Filename, @WorldName, @SizeBytes, @CreatedAt, @BackupType, @Notes)",
@@ -167,7 +175,6 @@ public void DeleteBackup(int backupId)
// Delete record
using (var conn = _db.CreateConnection())
{
- conn.Open();
Dapper.SqlMapper.Execute(conn,
"DELETE FROM backups WHERE id = @Id",
new { Id = backupId });
@@ -181,7 +188,6 @@ public List GetAll()
{
using (var conn = _db.CreateConnection())
{
- conn.Open();
return Dapper.SqlMapper.Query(conn,
"SELECT id as Id, filename as Filename, world_name as WorldName, size_bytes as SizeBytes, " +
"created_at as CreatedAt, backup_type as BackupType, notes as Notes " +
@@ -197,7 +203,6 @@ public BackupRecord GetBackup(int id)
{
using (var conn = _db.CreateConnection())
{
- conn.Open();
return Dapper.SqlMapper.QueryFirstOrDefault(conn,
"SELECT id as Id, filename as Filename, world_name as WorldName, size_bytes as SizeBytes, " +
"created_at as CreatedAt, backup_type as BackupType, notes as Notes " +
@@ -228,8 +233,7 @@ public void LoadSettings()
{
using (var conn = _db.CreateConnection())
{
- conn.Open();
- var json = Dapper.SqlMapper.QueryFirstOrDefault(conn,
+ var json = Dapper.SqlMapper.QueryFirstOrDefault(conn,
"SELECT value FROM settings WHERE name = 'backup_settings'");
if (!string.IsNullOrEmpty(json))
@@ -246,7 +250,6 @@ private void SaveSettings()
{
using (var conn = _db.CreateConnection())
{
- conn.Open();
var json = Newtonsoft.Json.JsonConvert.SerializeObject(_settings);
Dapper.SqlMapper.Execute(conn,
@"INSERT OR REPLACE INTO settings (name, value) VALUES ('backup_settings', @Value)",