我花了很多时间在Google上搜索并阅读了有关StackOverflow上有关SQLite的其他讨论,但我绝对无法找到对我的问题的任何解释,所以这里是:
上下文 :
我正在为iPad开发一个应用程序,它必须在某些情况下处理一些“大量”数据。在其中之一中,我必须将.kml文件(Google的用于地理数据的xml)中的点坐标导入到我的数据库中,以便以后在MKMapView中重用它们并比在需要显示特定内容时解析xml时加载速度更快。层。
细节 :
导入很容易:在处理这些文件时,我只关心2个表:
其中一个包含区域定义和详细信息:目前,一个integer
作为ID,一个text
用于命名。
一个包含两个real
用于坐标存储,一个integer
引用第一个表以了解哪个区域点是其中的一部分。
因此,只要读取我的文件,我就先为新区域创建一个条目,然后将点插入第二个表中,并在第一个表中创建最后一个区域的ID ...没有什么复杂的!
但...
问题 :
在运行了一段时间之后,我从SQLite收到了一条异常消息,并带有著名的消息“无法打开数据库文件”,然后我又无法对数据库进行任何操作。在区域创建或点插入方法中可能会随机发生此异常。
我的反思:
考虑到这些文件中的许多点,我怀疑内存或磁盘已饱和,但我的应用程序的其他部分却丢弃了这些点(在我看来)。
首先,内存:发生异常时,应用程序正在使用大约10或12 MB的RAM。它看起来可能非常大,但这是由于在内存中加载了〜10MB .kml文件,因此可以解释。最重要的是,我的应用程序中的MKMapView可以处理地图上方的大量高分辨率瓷砖图层,因此会导致内存高峰,该高峰可以提供20甚至25MB的内存而不会导致iPad崩溃。
其次,磁盘:重置数据库并仅填充上述2个表时,发生异常时的db文件大小始终约为2.2或2.5MB,但是当我填充其他表时(应用程序的其他部分运行良好!) db文件大约为6或7MB,设备完全没有抱怨。
所以呢?!
CPU焦虑和恐慌?我不这么认为,因为我数据库的其他一些表都以相同的节奏填充而没有问题...并且在模拟器中运行我的应用程序也崩溃了,而核心i7只是在嘲笑这项工作。
SQLite不好用吗?好了!在我看来,这是唯一的解决方案!但是我真的不明白这是怎么回事,因为我以与其他应用程序部分相同的方式处理请求-重复自己-就像一个魅力!
SQLite详细信息:
我有一个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数据库,然后使用该数据库将数据导入主数据库中(考虑较低的内存/处理器要求)
小批量处理导入的数据。
高温超导
编辑:您可能已经检查过,但是:unable to open database。
关于c# - SQLite问题“无法打开数据库文件”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7327460/