【问题标题】:Open/Close a database from a stream从流中打开/关闭数据库
【发布时间】:2014-05-25 12:13:24
【问题描述】:

我想从给定的流 (FileStream/Memorystream) 访问 SQLite 数据库?

这是我目前的代码(它将文件读入内存流,然后在 SQLite 中打开):

if (File.Exists(path_DB))
{
    byte[] file = File.ReadAllBytes(path_DB);
    MemoryStream mem = new MemoryStream(file);

    using (SQLiteConnection destination = new SQLiteConnection("Data Source=" + mem + ";Version=3;"))
    {
        destination.Open();

        using (SQLiteCommand command = new SQLiteCommand())
        {
            command.Connection = destination;
            command.CommandText = "SELECT Name FROM MyTable;";

            using (SQLiteDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    MessageBox.Show(reader["Name"].ToString());
                }
            }
        }
    }
}

这段代码触发了我

SQL 逻辑错误或缺少数据库,没有这样的表:MyTable

command.ExecuteReader()path_DB 引用的文件确实有该表。

我哪里出错了?

//编辑:已更改

byte[] file = File.ReadAllBytes(path_DB);
MemoryStream mem = new MemoryStream();

byte[] file = File.ReadAllBytes(path_DB);
MemoryStream mem = new MemoryStream(file);

此外,我可以将现有数据库加载到内存中,然后将内存数据库再次保存到磁盘,如下所示:

if (File.Exists(path_DB))
{
    using (SQLiteConnection destination = new SQLiteConnection("Data Source=:memory:;Version=3;"))
    {
        SQLiteConnection source = new SQLiteConnection("Data Source=" + path_DB + ";Version=3;"); //;Password=" + textBox2.Text + "
        source.Open();

        destination.Open();

        source.BackupDatabase(destination, "main", "main", -1, null, 0);
        source.Close();

        using (SQLiteCommand command = new SQLiteCommand())
        {
            command.Connection = destination;
            command.CommandText = "SELECT Name FROM MyTable;";

            using (System.Data.SQLite.SQLiteDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    MessageBox.Show(reader["Name"].ToString());
                }
            }
        }

        source = new SQLiteConnection("Data Source=" + path_DB + ";Version=3;"); //;Password=" + textBox2.Text + "
        source.Open();

        // save memory db to file
        destination.BackupDatabase(source, "main", "main", -1, null, 0);
        source.Close();
    }
}

所以我想,一定还有一种方法可以通过直接(解密)流来做到这一点!?

【问题讨论】:

    标签: c# sqlite


    【解决方案1】:

    您的代码和您正在尝试做的事情存在多个问题。

    首先,您分配给file,但没有对它做任何事情。

    接下来,您不能只将MemoryStream 实例附加到您的连接中。如图documentation

    强制 SQLite 数据库纯粹存在于内存中的最常见方法是使用特殊文件名“:memory:”打开数据库。换句话说,不是将真实磁盘文件的名称传递给 sqlite3_open()、sqlite3_open16() 或 sqlite3_open_v2() 函数之一,而是传递字符串“:memory:”。

    这意味着在连接字符串中,您需要:memory: 作为数据源。这也显示在https://www.connectionstrings.com/sqlite/

    Data Source=:memory:;Version=3;New=True;
    

    最后,我之前提到的文档中的另一个 sn-p:

    完成后,不会打开任何磁盘文件。相反,一个新的数据库是纯粹在内存中创建的。一旦数据库连接关闭,数据库就不再存在。每个 :memory: 数据库都彼此不同。因此,打开两个数据库连接,每个连接的文件名为“:memory:”,将创建两个独立的内存数据库。

    这意味着您不能使用现有数据库。您创建一个数据库,使用它,然后它再次被销毁。文件级别没有持久性。

    如果这一切对您来说毫无意义,而您只想使用驱动器上的数据库,请使用如下连接字符串:

    Data Source=c:\mydb.db;Version=3;
    

    SQLite 提供程序将负责打开文件、读取文件和写入文件。

    对于您的加密问题,you can use a password for the database。这将负责加密数据库

    Data Source=c:\mydb.db;Version=3;Password=myPassword;
    

    【讨论】:

    • 我从磁盘上的加密内容中读取我的流,然后再次想将其加密保存。
    • @user3079834 您使用哪个库来访问数据库?
    • 我从 nuget 获得的 SQLite 库(x86 和 x64 的标准库)
    • 你不能完全做到这一点。 SQLite 是一个 UNMANAGED NATIVE 库。它对System.IO.Stream 一无所知。理论上可以使用Memory Mapped Files 执行此操作,但由此产生的互操作混乱会使性能变得一团糟。
    • 然而真正让我困惑的是,SQLite 有一个内置的加密 API。你为什么不用那个?
    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2017-02-01
    • 1970-01-01
    相关资源
    最近更新 更多