【问题标题】:Make SQLite connection fail if database is missing? (deleted/moved)如果数据库丢失,使 SQLite 连接失败? (删除/移动)
【发布时间】:2016-09-15 16:47:10
【问题描述】:

我在class DBConnection 中有以下方法。当我想打开一个连接时,我调用这样的方法:SQLiteConnection conn = DBConnection.OpenDB();,以便我可以执行我的查询。当我想关闭连接时,我可以调用类似的方法。

方法:

public static SQLiteConnection OpenDB()
{
    try
    {
        //Gets connectionstring from app.config
        string myConnectString =
            ConfigurationManager.ConnectionStrings[
                "LegMedSQLLite.Properties.Settings.LegMedSQLLiteDBConnectionString"].ConnectionString;

        var conn = new SQLiteConnection(myConnectString);

        conn.Open();
        return conn;
    }
    catch (SQLiteException e)
    {
        MessageBox.Show(e.ToString(), "TEST");
        return null;
    }
}

这一切都很好而且花花公子。问题是尝试捕获。让我们想象以下场景:

  • 数据库文件已被 移动/删除。

永远不会抛出异常。实际上,我偶然发现的第一个问题是当我执行我的第一个查询时 - 它认为没有这样的表并且它抛出了自己的异常。 我被这个奇怪的现象惊呆了,但我很快发现 SQLite 创造了一个新的 数据库。空的意思是没有表,什么都没有,只是一个与应该存在的旧数据库同名的 SQLite 数据库文件。

这是一个问题,我希望应用程序在我尝试调用 SQLiteConnection conn = DBConnection.OpenDB(); 时立即知道是否有问题(数据库未找到、损坏、被另一个进程使用等)。

当然,我可以尝试在我的方法中调用 File.Exists,但这似乎不是一个合适的解决方案。有什么帮助吗?

【问题讨论】:

    标签: c# sqlite


    【解决方案1】:

    至少在 System.Data.SQLite 中,您可以将“FailIfMissing=True”添加到您的连接字符串中。如果数据库文件不存在,SQLiteConnection.Open() 将抛出 SQLiteException

    string ConnectString = "Data Source=file.sdb; FailIfMissing=True";
    DbConnection db = new SQLiteConnection(ConnectString);
    db.Open(); // Fails if file.sdb does not exist
    

    另一个例子见SQLite Connection String Samples,寻找“禁用创建数据库行为”。

    【讨论】:

      【解决方案2】:

      我没有使用过 SQLite,但自动创建全新数据库的行为非常奇怪。

      您可以在打开连接后立即调整您的尝试块以执行Select top 1 * From Table,如果它有效,则丢弃结果并继续返回您的conn 对象。如果失败,则应触发异常处理程序。

      【讨论】:

      • 是的,我也这么认为!但它似乎不仅仅是 System.Data.SQLite 这样做。我知道 SQLite 网络服务器使用的也是如此。另外,我也想到了 SQL 查询的想法,但这似乎是一种浪费。如果没有“正确”的方法可以做到这一点,我肯定会将您的答案标记为已接受的答案。
      【解决方案3】:

      如果要在启动时检测数据库损坏问题,可以执行命令

      编译指示完整性检查;

      编译指示快速检查; (速度更快,但不够彻底)

      这将返回值为“ok”的单行。

      否则它会报告它遇到的错误。

      【讨论】:

        【解决方案4】:

        对于 sqlite 使用这个:假设你在文本框 txtConnSqlite 中有连接字符串

             Using conn As New System.Data.SQLite.SQLiteConnection(txtConnSqlite.Text)
                    Dim FirstIndex As Int32 = txtConnSqlite.Text.IndexOf("Data Source=")
                    If FirstIndex = -1 Then MsgBox("ConnectionString is incorrect", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
                    Dim SecondIndex As Int32 = txtConnSqlite.Text.IndexOf("Version=")
                    If SecondIndex = -1 Then MsgBox("ConnectionString is incorrect", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
                    Dim FilePath As String = txtConnSqlite.Text.Substring(FirstIndex + 12, SecondIndex - FirstIndex - 13)
                    If Not IO.File.Exists(FilePath) Then MsgBox("Database file not found", MsgBoxStyle.Exclamation, "Sqlite") : Exit Sub
                    Try
                        conn.Open()
                        Dim cmd As New System.Data.SQLite.SQLiteCommand("SELECT * FROM sqlite_master WHERE type='table';", conn)
                        Dim reader As System.Data.SQLite.SQLiteDataReader
                        cmd.ExecuteReader()
                        MsgBox("Success", MsgBoxStyle.Information, "Sqlite")
                    Catch ex As Exception
                        MsgBox("Connection fail", MsgBoxStyle.Exclamation, "Sqlite")
                    End Try
                 End Using
        

        我认为您可以轻松地将其转换为 c# 代码

        【讨论】:

          【解决方案5】:

          不要在那个级别上赶上。相反,SQLiteConnection 应该实现 IDisposable,这意味着您应该只返回打开的连接并允许调用代码处理任何异常,并依赖 Dispose 方法来关闭连接。

          【讨论】:

            【解决方案6】:

            如果无法更改默认 SQLite 行为,那么您可能必须执行 File.Exists。这比连接并创建一个新文件,检查它是否是您想要的数据库,然后在 catch 块中删除新文件要好。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-03-13
              • 2013-04-27
              • 1970-01-01
              • 2017-05-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多