You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite插入未提交引发异常:索引是否损坏及提交语法咨询

问题描述

我正在开发一款用于天文摄影的个人C# Windows Form工具应用,此前多次从仓库恢复代码,SQLite数据库已受损,怀疑索引出现问题(可重建数据库)。

代码逻辑为先查询数据库中是否已记录目标,再执行插入操作。

查询代码

string connectionString = "Data Source=..\\..\\Astrophotography DataBase\\Astrophotography.db;Version=3;";

public bool QueryATI(string strTargetName, string[] arrEquipment)
{
    using (SQLiteConnection conn = new SQLiteConnection(connectionString))
    {
        conn.Open();
        bool result = false; 
        SQLiteCommand command =
             new SQLiteCommand("SELECT ATI_TargetName, ATI_Telescope_Lens_Used FROM Astro_Target_Imaged WHERE ATI_TargetName = @Target", conn);
        command.Parameters.Add(new SQLiteParameter("@Target", strTargetName));
        using (SQLiteDataReader TargetReader = command.ExecuteReader())
        {
            int i = 0;
            
            if (TargetReader.HasRows)
            {
             // It is very possible  a target has been imaged more than once with different
             // equipment or focal lengths.  This checks to see what has been recorded of 
             // any of them, and if this one is not recorded.  It will be added.
                {
                    string strTelescope = TargetReader["ATI_Telescope_Lens_Used"].ToString();
                    string strArrayValue = arrEquipment[i].ToString();
                    if (strTelescope == arrEquipment[i])
                    {
                        result = true;
                        conn.Clone();
                        return result;
                    }
                    i++;
                }
            }
            result = false;
            conn.Clone();
            return result;
        }
          
       
        result = false;
        conn.Clone();
        return result;
    }
   
}

插入代码

public void BuildATI(string strTargetName, string strMount, string strICamera, string strTelescope, string strFilter, string strGuidCamera, string strGuideScope)
{
    using (SQLiteConnection conn = new SQLiteConnection(connectionString))
    {
        conn.Open();
        bool result = false;
        string strInsert = ("INSERT INTO Astro_Target_Imaged");
        string strColumns = "(ATI_TargetName, ATI_Mount_Used, ATI_Image_Camera, ATI_Telescope_Lens_Used, ATI_Filter, ATI_Guide_Camera, ATI_Guide_Scope_Used)";
        string strValues = "VALUES (@Target, @Mount, @ICamera, @Telescope, @Filter, @GCamera, @GScope)";
        string strQuery = strInsert + strColumns + strValues;   
        SQLiteCommand command =
             new SQLiteCommand(strQuery, conn);
        command.Parameters.Add(new SQLiteParameter("@Target", strTargetName));
        command.Parameters.Add(new SQLiteParameter("@Mount", strMount));
        command.Parameters.Add(new SQLiteParameter("@ICamera", strICamera));
        command.Parameters.Add(new SQLiteParameter("@Telescope", strTelescope));
        command.Parameters.Add(new SQLiteParameter("@Filter", strFilter));
        command.Parameters.Add(new SQLiteParameter("@GCamera", strGuidCamera));
        command.Parameters.Add(new SQLiteParameter("@GScope", strGuideScope));
        //.FirstOrDefault();

        try
        {
            command.ExecuteNonQuery();
            //conn.Commit();
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
                        
        conn.Clone();
    }

}

问题现象

插入操作无报错,但在SQLiteStudio中查询不到数据;再次运行相同数据时,查询代码判断存在行,但访问列时抛出“无行”异常,怀疑数据库索引损坏。

现咨询:

  1. 数据库索引是否已损坏?
  2. SQLite的提交语句语法是什么?

解答

一、数据库索引是否损坏?

目前的现象更可能是代码逻辑错误导致的,而非索引损坏,但也不能完全排除数据库损坏的可能,先优先排查代码问题:

代码中的关键错误

  1. conn.Clone() 误用:所有出现 conn.Clone() 的地方都应该是 conn.Close(),Clone() 是创建连接副本的方法,不是关闭连接。未正确关闭连接可能导致事务未正常提交,数据无法持久化到磁盘。
  2. DataReader 未正确读取行:QueryATI 方法中,TargetReader.HasRows 为真时,未调用 TargetReader.Read() 移动到有效行就直接访问列,这会直接抛出“无行”异常;同时代码只尝试检查一次,没有循环遍历所有匹配的行来对比设备数组。
  3. 路径与连接释放问题:using 块会自动释放连接,无需显式调用 Close(),但错误的 Clone() 操作可能干扰连接的正常释放流程;另外要确认连接字符串中的数据库路径是否正确,避免写入到非预期的目录(比如调试和发布环境的路径差异)。

排查数据库损坏的方法

如果修正代码后问题仍存在,可执行以下操作验证:

  • 使用SQLite命令行工具执行 PRAGMA integrity_check;,检查数据库完整性。
  • 重建数据库:将现有数据导出为SQL脚本,创建新数据库后导入脚本。

二、SQLite的提交语句语法

SQLite 默认开启自动提交(AutoCommit),执行 INSERT/UPDATE/DELETE 后会自动提交事务。如果手动开启了事务(使用 BEGIN TRANSACTION;),需要手动提交,语法为:

COMMIT;

若需要回滚事务则使用:

ROLLBACK;

在C#代码中手动控制事务的示例:

using (SQLiteConnection conn = new SQLiteConnection(connectionString))
{
    conn.Open();
    using (SQLiteTransaction tran = conn.BeginTransaction())
    {
        try
        {
            SQLiteCommand command = new SQLiteCommand(insertQuery, conn, tran);
            command.ExecuteNonQuery();
            tran.Commit(); // 手动提交事务
        }
        catch (Exception ex)
        {
            tran.Rollback(); // 出错时回滚
            throw ex;
        }
    }
}

代码修正建议

  1. 替换所有 conn.Clone() 为 conn.Close(),或者直接删除这些调用(using 块会自动释放连接)。
  2. 修正 QueryATI 中的DataReader读取逻辑:
if (TargetReader.HasRows)
{
    while (TargetReader.Read()) // 循环读取所有匹配行
    {
        string strTelescope = TargetReader["ATI_Telescope_Lens_Used"].ToString();
        foreach (string equip in arrEquipment) // 遍历设备数组对比
        {
            if (strTelescope == equip)
            {
                result = true;
                return result;
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者OldAndRetired

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:11:06