SQLite问题“无法打开数据库文件”
本文关键字:数据库 文件 问题 SQLite | 更新日期: 2023-09-27 18:07:53
我在StackOverflow上搜索和阅读了很多关于SQLite的讨论后找到了你,但我绝对找不到任何解释我的问题,所以这里是:
-
上下文:
我正在为iPad开发一个应用程序,它必须在几个场合处理一些"大量"数据。在其中一个,我必须从一个。kml文件(谷歌的xml地理数据)导入点坐标到我的数据库中,以便以后用MKMapView重用它们,并且在需要显示特定层时加载它们比解析xml更快。 -
详细信息:
导入的事情很简单:当处理这些文件时,我只关心两个表:- 一个包含区域定义和详细信息:目前,
integer
作为id,text
用于命名。 - 一个包含两个
real
用于坐标存储,一个integer
引用第一个表,用于知道哪个区域点属于该区域。
因此,只要读取我的文件,我首先为新区域创建一个条目,然后在第二个表中插入点,在第一个表中创建的最后一个区域的ID…没有什么复杂的!
但是…
- 一个包含区域定义和详细信息:目前,
-
问题:
运行良好一段时间后,我得到一个异常从SQLite与著名的消息"无法打开数据库文件",然后它来了,我不能做任何更多的数据库。此异常可能在区域创建或点插入方法中随机发生。 -
My reflexions:
考虑到这些文件中的许多点,我怀疑内存或磁盘饱和,但我的应用程序的其他部分丢弃了这些点(在我看来)。首先是内存:当异常发生时,应用程序正在使用大约10或12 MB的RAM。它看起来非常大,但这是由于内存中加载了大约10MB的.kml文件,所以这是可以解释的。最重要的是,我的应用程序的MKMapView处理地图上的大量高分辨率磁贴层,这导致内存峰值可以达到20甚至25MB,而不会导致iPad崩溃。第二,磁盘:当重置我的数据库并只填充上面描述的2个表时,异常发生时的db文件大小总是大约2.2或2.5MB,但当我填充其他表时(我的应用程序的其他部分工作良好!)db文件大约是6或7MB,设备根本没有抱怨。 -
那又怎样? !
cpu——愤怒和恐慌?我不这么认为,因为我的数据库的一些其他表是在相同的节奏填充没有问题…在模拟器中运行我的应用程序也会崩溃,core i7只是在嘲笑这个工作。SQLite使用不当?好了!在我看来,这是唯一的解决办法!但我真的不明白这里发生了什么,因为我处理我的请求的方式和我在其他应用程序的部分一样——重复我自己——像魅力一样工作! -
SQLite details:
我有一个DB
类,这是一个单例,我用它来避免创建/释放SqliteConnection
对象,我做的每个请求,我所有处理数据库的方法都包含在这个类中,以确保我不会在其他任何地方玩连接而不知道它。以下是该类的相关方法:public void saveZone(ObjZone zone) { //at this point, just creates an entry with a name and let sqlite give it a new id lock (connection) { //SqliteConnection object try { openConnection(); SqliteCommand cmd = connection.CreateCommand(); cmd.CommandText = zone.id == 0 ? "insert into ZONES (Z_NAME) values (" + format(zone.name) + ") ;" : "update ZONES set Z_NAME = " + format(zone.name) + " where Z_ID = " + format(zone.id) + " ;"; cmd.ExecuteNonQuery(); if (zone.id == 0) { cmd.CommandText = "select Z_ID from ZONES where ROWID = last_insert_rowid() ;"; zone.id = uint.Parse(cmd.ExecuteScalar().ToString()); } cmd.Dispose(); } catch (Exception e) { Log.failure("DB.saveZone(" + zone.ToString() + ") : [" + e.GetType().ToString() + "] - " + e.Message + "'n" + e.StackTrace); //custom Console.WriteLine() method with some formating throw e; } finally { connection.Close(); } } } public void setPointsForZone(List<CLLocationCoordinate2D> points, uint zone_id) { //registers points for a given zone lock (connection) { try { openConnection(); SqliteCommand cmd = connection.CreateCommand(); cmd.CommandText = "delete from ZONESPOINTS where Z_ID = " + format(zone_id); cmd.ExecuteNonQuery(); foreach(CLLocationCoordinate2D point in points) { cmd.CommandText = "insert into ZONESPOINTS values " + "(" + format(zi_id) + ", " + format(point.Latitude.ToString().Replace(",", ".")) + ", " + format(point.Longitude.ToString().Replace(",", ".")) + ");"; cmd.ExecuteNonQuery(); cmd.Dispose(); } } catch (Exception e) { Log.failure("DB.setPointsForZone(" + zone_id + ") : [" + e.GetType().ToString() + "] - " + e.Message); throw e; } finally { connection.Close(); } } }
为了尽可能清楚,这里是上面两个引用的一些方法(我使用这个自定义
openConnection()
方法,因为我在大多数表中使用外键约束,默认情况下级联行为不启用,但我需要它们):void openConnection() { try { connection.Open(); SqliteCommand cmd = connection.CreateCommand(); cmd.CommandText = "PRAGMA foreign_keys = ON"; cmd.ExecuteNonQuery(); cmd.Dispose(); } catch (Exception e) { Log.failure("DB.openConnection() : [" + e.GetType().ToString() + "] - " + e.Message); throw e; } } public static string format(object o) { return "'" + o.ToString().Replace("'", "''") + "'"; }
好吧,对不起,小说,我可能已经感谢你读了所有的东西,不是吗?不管怎样,如果我遗漏了什么有用的东西,请告诉我,我会尽快记录下来。我希望有人能帮助我,无论如何,提前谢谢你!
(我为我可怜的法国人的英语道歉。)
编辑
我的问题"解决了"!为了调试目的,我做了一些修改,没有大的修改,也没有成功,于是我把代码放回了发布时的状态……现在它成功了。但如果有人能给我解释一下发生了什么,我真的会很感激的!似乎SQLite的行为(至少在iPad上-从未在其他地方使用过)有时会相当模糊…:/
我不会交叉手指,但我会尝试两件事:
- 如果可能的话,将KML文件预处理到第二个SQLite数据库,并使用该数据库在主数据库中导入数据(考虑较低的内存/处理器要求)
- 小批量处理导入数据。
HTH
编辑:你可能已经检查过了,但是无论如何:无法打开数据库。