如何在 .NET DLL 中嵌入 SQLite 数据库,然后从 C# 中使用它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/791198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:16:29  来源:igfitidea点击:

How can I embed a SQLite Database in a .NET DLL and then use it from C#?

c#.netsqlitedllembed

提问by chrischu

I'm currently working on some evaluation work for a project that I'm planning.

我目前正在为我正在计划的项目进行一些评估工作。

I recently looked at solutions for a data storage mechanism for my application and while researching stumbled upon SQLite. I currently use SQLite with the System.Data.SQLite wrapper.

我最近为我的应用程序研究了数据存储机制的解决方案,并在研究时偶然发现了 SQLite。我目前将 SQLite 与 System.Data.SQLite 包装器一起使用。

I really like the way it works but I have one problem with it that I couldn't get fixed and I also found no help concerning my problem on the internet.

我真的很喜欢它的工作方式,但我有一个无解决的问题,而且我在互联网上也没有找到有关我的问题的帮助。

I would like my SQLite Database to be embedded into one of my applications DLLs (ie. Title.Storage.dll) to be used within this DLL. Is this possible?

我希望将我的 SQLite 数据库嵌入到我的应用程序 DLL 之一(即 Title.Storage.dll)中,以便在此 DLL 中使用。这可能吗?

How can I access the database then?

那么如何访问数据库呢?

It would be great if I could use something like:

如果我可以使用类似的东西,那就太好了:

SQLiteConnection con = new SQLiteConnection();
con.ConnectionString="DataSource=Title.Storage.storage.db3";
con.Open();

Thanks in advance and best regards,

提前致谢并致以最诚挚的问候,

3Fox

3狐狸

采纳答案by Samuel

An assembly isn't for file storage, it's for code storage. While you can store files in an assembly, they are read only.

程序集不是用于文件存储,而是用于代码存储。虽然您可以将文件存储在程序集中,但它们是只读的。

回答by Anthony Brien

If you're on NTFS, you can use an alternate data stream. On my project we hide the SQLite database inside another file using an alternate stream called :DB.

如果您使用的是 NTFS,则可以使用备用数据流。在我的项目中,我们使用名为 :DB 的备用流将 SQLite 数据库隐藏在另一个文件中。

回答by Anthony Brien

SQLite is packaged and distributed as a single C file with a few (3 I think) header files. This means that you can compile the entire 50000 line program with one compile command and get a .o file. From there, you can link it into your application DLL with the other files you link into that DLL.

SQLite 作为单个 C 文件打包和分发,其中包含一些(我认为是 3 个)头文件。这意味着您可以使用一个编译命令编译整个 50000 行程序并获得一个 .o 文件。从那里,您可以将它与您链接到该 DLL 的其他文件一起链接到您的应用程序 DLL。

Once you build sqlite3.o into your application DLL, the symbols in its SQLite's API become available to your programs in the same way that your other C/C++ DLLs become available to your C#/VB programs.

一旦您将 sqlite3.o 构建到您的应用程序 DLL 中,它的 SQLite API 中的符号就可用于您的程序,就像您的其他 C/C++ DLL 可用于您的 C#/VB 程序一样。

Check out www.sqlite.org/amalgamation.html for more info.

查看 www.sqlite.org/amalgamation.html 了解更多信息。

回答by mateusza

I don't think storing data in DLL is a good idea, but there is a dirty way to do it.

我不认为将数据存储在 DLL 中是一个好主意,但有一种肮脏的方可以做到这一点。

To load data from DLL:

从 DLL 加载数据:

  1. Use System.Reflection.Assembly to load a string from DLL file. (The string is dump of DB)
  2. Create empty SQLite DB in memory.
  3. Use the loaded string as a query to DB to restore its content.
  1. 使用 System.Reflection.Assembly 从 DLL 文件加载字符串。(字符串是 DB 的转储)
  2. 在内存中创建空的 SQLite DB。
  3. 使用加载的字符串作为对 DB 的查询以恢复其内容。

Now you can make any queries in memory.

现在您可以在内存中进行任何查询。

To save data to DLL:

将数据保存到 DLL:

  1. Dump DB content into a string.
  2. Create temporary file containing SQL-dump wrapped in C# code.
  3. Compile it using "csc" (or "gmcs" in Mono).
  1. 将数据库内容转储为字符串。
  2. 创建包含用 C# 代码包装的 SQL-dump 的临时文件。
  3. 使用“csc”(或 Mono 中的“gmcs”)编译它。

It's stupid, but it should work. Hope you will never code that way.

这很愚蠢,但它应该有效。希望你永远不会那样编码。

回答by nawfal

This is not possible as such. What you could do is embed the db in your dll project and dump it to certain location on the file system (may be AppData?) and read and write from there. Having db sit directly inside the executable (or dlls) may not be a good idea in the sense it bloats the size of the application besides being technically infeasible.

这是不可能的。您可以做的是将 db 嵌入到您的 dll 项目中,并将其转储到文件系统上的某个位置(可能是 AppData?),然后从那里读取和写入。将 db 直接放在可执行文件(或 dll)中可能不是一个好主意,因为除了技术上不可行之外,它还会膨胀应用程序的大小。

Having a single executable to distribute is a matter of taste which I like. In your case but the problems are more. It's not just about embedding the db file alone, what about the dlls associated with it? Steps are 2:

有一个单独的可执行文件要分发是我喜欢的品味问题。在你的情况下,但问题更多。这不仅仅是关于单独嵌入 db 文件,与它相关的 dll 怎么样?步骤是2:

1) Add the necessary dlls (System.Data.SQLite?) associated with your db to your project as Embedded Resource(not necessarily a Resource file)and let the system automatically resolve the assembly conflicts. Catch it herehow to do it.

1) 将System.Data.SQLite与您的 db 关联的必要 dll(?)添加到您的项目中Embedded Resource(不一定是Resource file),并让系统自动解决程序集冲突。在这里抓住它怎么做。

2) Now either add your db file to your Resourcesof your project (and extract it)

2)现在将您的db文件添加到您Resources的项目中(并提取它)

static void DumpDatabase()
{
    var dbFullPath = Utility.GetDbFullPath(); //your path
    if (File.Exists(dbFullPath))
        return; //whatever your logic is

    File.WriteAllBytes(dbFullPath, Properties.Resources.myDb);
}

or even betterdo not embed the db as such in your project but write the logic to create database in your application. What if tomorrow you need to change the version of SQLite, say from 3 to 4? With the first approach you need to create a database for yourself and re-embed it in the project. But if you are writing the logic to create the db in your application then updating SQLite version is just a matter of changing the ADO.NET dll (the code remains the same). May be like this:

或者最好不要将数据库嵌入到您的项目中,而是编写逻辑以在您的应用程序中创建数据库。如果明天您需要更改 SQLite 的版本,例如从 3 更改为 4,该怎么办?使用第一种方,您需要为自己创建一个数据库并将其重新嵌入到项目中。但是,如果您正在编写在应用程序中创建数据库的逻辑,那么更新 SQLite 版本只是更改 ADO.NET dll 的问题(代码保持不变)。可能是这样的:

static void DumpDatabase()
{
    var dbFullPath = Utility.GetDbFullPath();
    if (File.Exists(dbFullPath))
        return; //whatever your logic is

    CreateDb(dbFullPath);
}

static void Create(string dbFullPath)
{
    SQLiteConnection.CreateFile(dbFullPath);

    string query = @"

    CREATE TABLE [haha] (.............)
    CREATE TABLE ..............";

    Execute(query);
}

And in the connection string add FailIfMissing=False;

并在连接字符串中添加 FailIfMissing=False;