简体   繁体   English

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

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

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. 我最近查看了针对我的应用程序的数据存储机制的解决方案,同时研究偶然发现了SQLite。 I currently use SQLite with the System.Data.SQLite wrapper. 我目前使用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. 我希望我的SQLite数据库嵌入到我的应用程序DLL(即Title.Storage.dll)中,以便在此DLL中使用。 Is this possible? 这可能吗?

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 3Fox

An assembly isn't for file storage, it's for code storage. 程序集不用于文件存储,而是用于代码存储。 While you can store files in an assembly, they are read only. 虽然您可以将文件存储在程序集中,但它们是只读的。

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. 你可以做的是将db嵌入你的dll项目并将其转储到文件系统上的某个位置(可能是AppData?)并从那里读写。 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)中可能不是一个好主意,因为除了技术上不可行之外,它还会增加应用程序的大小。

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? 它不只是单独嵌入db文件,与它相关的dll怎么样? Steps are 2: 步骤是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. 1)将与数据库关联的必要dll( System.Data.SQLite ?)作为Embedded Resource (不一定是Resource file )添加到项目中,让系统自动解决程序集冲突。 Catch it here how to do it. 抓住它在这里如何做到这一点。

2) Now either add your db file to your Resources of 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 better do 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? 如果明天你需要更改SQLite的版本,比如从3到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). 但是如果你正在编写在应用程序中创建数据库的逻辑,那么更新SQLite版本只需要更改ADO.NET dll(代码保持不变)。 May be like this: 可能是这样的:

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;

If you're on NTFS, you can use an alternate data stream. 如果您使用的是NTFS,则可以使用备用数据流。 On my project we hide the SQLite database inside another file using an alternate stream called :DB. 在我的项目中,我们使用名为DB的备用流将SQLite数据库隐藏在另一个文件中。

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

Now you can make any queries in memory. 现在你可以在内存中进行任何查询。

To save data to DLL: 要将数据保存到DLL:

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

It's stupid, but it should work. 这是愚蠢的,但应该有效。 Hope you will never code that way. 希望你永远不会这样编码。

SQLite is packaged and distributed as a single C file with a few (3 I think) header files. SQLite打包并作为单个C文件分发,其中包含一些(我认为3个)头文件。 This means that you can compile the entire 50000 line program with one compile command and get a .o file. 这意味着您可以使用一个编译命令编译整个50000行程序并获取.o文件。 From there, you can link it into your application DLL with the other files you link into that DLL. 从那里,您可以将其链接到您的应用程序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。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM