【问题标题】:sqlite unable to open database file is encrypted or is not a database?sqlite无法打开数据库文件是加密还是不是数据库?
【发布时间】:2020-11-23 05:22:56
【问题描述】:

我正在开发带有 sqlite 数据库的 Windows 应用程序 .net 2.0,我的连接字符串保留在 app.config 中

<connectionStrings>
<add name="SQLiteDB" 
     connectionString="Data Source=|DataDirectory|database.s3db;version=3;password=mypassword;" 
     providerName="System.Data.Sqlite"/>
</connectionStrings>

在连接字符串中,我将密码定义为“mypassword”,如果我删除此密码,一切正常,但是当我使用密码子句时,它在 connection.open() 语法中出现错误

File opened that is not a database file
file is encrypted or is not a database

我在网上搜索并发现了一些版本问题,但我只使用版本 3,正如我在连接字符串中所述,我还尝试删除“version=3”,但问题仍然存在。

我是第一次这样做,有什么解决办法?

【问题讨论】:

  • 我收到此错误消息是因为我尝试使用 sqlite 打开 db 文件,但我应该使用的是 sqlite3

标签: c# winforms visual-studio-2010 sqlite


【解决方案1】:

当您在连接字符串中指定密码并且数据库已经存在时,SQLite 假定数据库已加密并尝试使用该密码对其进行解密。如果您尚未在数据库上设置密码,这将导致“文件已加密”错误,因为提供的密码不能用于解密未加密的数据库。

您可以删除数据库,SQLite 将使用连接字符串中的密码创建一个新的加密数据库。或者,您可以使用ChangePassword() 方法加密现有数据库:

// Opens an unencrypted database    
SQLiteConnection cnn = new SQLiteConnection("Data Source=c:\\test.db3");    
cnn.Open();    

// Encrypts the database. The connection remains valid and usable afterwards.    
cnn.ChangePassword("mypassword");

参考:Encrypting, decrypting and attaching to encrypted databases

【讨论】:

  • +1,非常感谢它可以正常工作,但只有第一次它可以完美运行,但是当我第二次运行应用程序时,它再次在 con.open 上显示相同的异常,即“打开的文件不是数据库文件文件被加密或不是数据库”
  • @harhar 请概述您为加密数据库所采取的步骤。如果您使用了ChangePassword() 方法,您需要将其从后续调用中删除。
  • 在 con.Open() 之后;我写 con.ChangePassword("password");在使用它之后我会 con.ChangePassword("");最后是 con.Close();有错吗?
  • @harhar 如果你想在连接字符串中指定密码,然后调用ChangePassword("mypassword") 一次设置数据库的加密(并且不要再次调用它,除非你真的想改变密码)。完全删除对 ChangePassword("") 的调用,因为这会从您的数据库中删除加密 - 这就是为什么下次您尝试使用连接字符串密码打开它时,您会再次收到“文件已加密”错误。
  • 我不明白为什么当您尝试conn.ChangePassword("") 时会再次收到“文件已加密”的错误,如果您通过清空密码来删除加密。但是,如果您使用字符串中的密码调用数据库,我发现会发生这种情况 - 数据库可能正在尝试使用该密码进行解密,并且在删除密码时会删除加密。 conn.SetPassword("something"); conn.Open(),并在连接字符串中使用该密码调用它。要更改它,您可以通过更改将其空白,但是您必须从连接字符串中删除密码参数。
【解决方案2】:

2Toad 的回答大部分是正确的,但我想添加我自己的,因为需要进行一些澄清。正如 2Toad 所说,这是正确的:

当您在连接字符串中指定密码并且数据库已经存在时,SQLite 假定数据库已加密,并会尝试使用该密码对其进行解密。如果您尚未在数据库上设置密码,这将导致“文件已加密”错误,因为提供的密码不能用于解密未加密的数据库。

但是,如果您在连接字符串中已有另一个 conn.SetPassword("something") 后尝试使用此错误,也会发生此错误。或者如果您使用conn.ChangePassword("somethingelse"),但在连接字符串中仍然有Password=something

有几种情况需要考虑:

  1. 数据库已应用密码,密码在连接字符串中。
  2. 连接字符串中有密码,但数据库没有应用密码,或者字符串中的密码与数据库不匹配。
  3. 数据库从未有过密码,您想更改它。
  4. 数据库有密码,您想更改它。

决议:

  1. 因此,2Toad 提供的用于执行conn.ChangePassword("somethingelse") 的代码只正确了一半,并且没有考虑到您在哪里、您还做了什么以及您将来想做什么。如果您有一个现有的密码并且想要更改它,这是正确的,但您还必须确保连接字符串在之后更新,否则后续连接将失败并出现 file is encrypted 错误。

  2. 1234563 Password=something 必须从连接字符串中删除,因为密码已以编程方式从数据库中删除,数据库将尝试与之连接。如果它没有在以编程方式从数据库中删除的同时从连接字符串中删除,您将收到相同的file is encrypted 错误。
  3. 因为我一开始是在没有应用密码的情况下使用conn.SetPassword("something") 开始的(我相信这是这样做的方法),如果不创建另一个密码,我无法验证以下内容SQLite DB,但如果您一开始就没有密码,我不相信您可以致电conn.ChangePassword("something")。您应该为初始设置执行conn.SetPassword("something"),然后将Password=something 放入您的连接字符串中。

  4. 我更改密码的方式是在conn.ChangePassword("somethingelse") 之后才进行conn.SetPassword("") 并从连接字符串中清除Password=something

    // Changes an encrypted database to unencrypted and removes password
    string connString = "Data Source=c:\\test.db3;Password=something";    
    SQLiteConnection conn = new SQLiteConnection(connString);
    conn.SetPassword("");
    //conn.Open();    // doesn't work because connString hasn't been updated
    
    // Update connString
    connString = "Data Source=c:\\test.db3;";    
    conn = new SQLiteConnection(connString);
    conn.Open();  // we've opened the DB without a password
    
    // Re-encrypts the database. The connection remains valid and usable afterwards until closed - then the connection string needs updating.    
    conn.ChangePassword("somethingelse");
    conn.Close();
    
    // Update connString
    connString = "Data Source=c:\\test.db3;Password=somethingelse";   
    conn = new SQLiteConnection(connString); // must re-instantiate!
    conn.Open();  // we've opened the DB with our new password
    

结果很好。我想您也不能从连接字符串中清除它,只需执行conn.ChangePassword("somethingelse"),然后将Password=somethingelse 添加到您的字符串中,然后:

    // Opens an encrypted database   
    string connString = "Data Source=c:\\test.db3;Password=something";    
    SQLiteConnection conn = new SQLiteConnection(connString);
    conn.Open();    

    // Encrypts the database. The connection remains valid and usable afterwards until closed - then the connection string needs updating.    
    conn.ChangePassword("somethingelse");
    conn.Close();

    // Update connString
    connString = "Data Source=c:\\test.db3;Password=somethingelse";   
    conn = new SQLiteConnection(connString);
    conn.Open();     // we've opened the DB with our new password

就个人而言,我将密码以加密形式存储在应用程序(Web).config 文件中,并将其调用到我的应用程序 onload 中的变量中,并从中动态构建我的连接字符串。

据我所知,如果你删除一个 SQLite DB 并尝试调用它,你只会得到一个错误 - 而不是使用连接字符串中的新密码重新创建的 SQLite DB - 至少在使用和调用它时来自 C# .NET 应用程序。

更新如果你需要一个函数来更新你已经拥有的密码,你不想拥有.SetPassword(),而是.ChangePassword()。我发现最好总是将其空白,然后更改它,就像我在 #4 中的第一个示例一样。

【讨论】:

    【解决方案3】:

    检查 SQLite 的版本。有些数据库只能通过sqlite3打开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-29
      • 2014-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      • 2014-11-11
      相关资源
      最近更新 更多