SQLite共享内存数据库异常生成磁盘文件问题排查
你遇到的问题本质是SQLite驱动没有正确识别你指定的Mode=Memory和Cache=Shared参数,转而创建了磁盘数据库文件,而非你期望的共享内存数据库,具体原因和解决方法如下:
为什么会生成sharedmemdb文件?
SQLite的连接字符串对格式要求很严格:参数的键和值之间不能有多余空格。比如你第二次代码里的Data Source =sharedmemdb、Mode = Memory,这些等号前后的空格会被驱动当成参数名的一部分(比如把Mode 当成参数名,而非Mode),导致Mode=Memory和Cache=Shared这两个关键参数完全失效。
当这两个参数失效时,SQLite会默认创建磁盘数据库,也就是你在应用目录里看到的sharedmemdb文件。第一次运行时这个文件不存在,所以能正常建表插入数据;但重启应用后,这个磁盘文件还在,表结构也保留着,再执行CREATE TABLE自然会抛出“Table already exists”的错误。
哪怕是你第一次的代码,看起来连接字符串没有空格,也可能存在隐藏的格式问题(比如复制粘贴时带入的不可见空格),导致同样的参数解析失败。
正确的解决方法
1. 修正连接字符串格式
必须严格去除参数键值对之间的空格,正确的连接字符串应该是:
var connectionString = "Data Source=sharedmemdb;Mode=Memory;Cache=Shared";
这个格式下,驱动才能正确识别Mode=Memory(指定使用内存数据库)和Cache=Shared(允许多个连接共享该内存数据库)的参数。
2. 理解共享内存数据库的生命周期
共享内存数据库的生命周期和连接绑定:只有当最后一个连接到该数据库的连接关闭时,内存中的数据才会被销毁。你的代码中两个连接都在using块内,执行完毕后会自动关闭,所以下次启动应用时,内存数据库已经不存在,不会出现表已存在的问题。
修正后的完整代码示例
var connectionString = "Data Source=sharedmemdb;Mode=Memory;Cache=Shared"; using (var connection1 = new SQLiteConnection(connectionString)) { connection1.Open(); using (var command1 = connection1.CreateCommand()) { command1.CommandText = "CREATE TABLE Message ( Text TEXT );" + "INSERT INTO Message ( Text ) VALUES ( 'Is there anybody out there?' );"; command1.ExecuteNonQuery(); } using (var connection2 = new SQLiteConnection(connectionString)) { connection2.Open(); using (var command2 = connection2.CreateCommand()) { command2.CommandText = "SELECT Text FROM Message;"; var message = command2.ExecuteScalar() as string; } } }
这样修改后,重启应用再运行,就不会生成磁盘文件,也不会出现表已存在的错误了。
内容的提问来源于stack exchange,提问作者Abhishek

