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上-从未在其他地方使用过)有时会相当模糊…:/

SQLite问题“无法打开数据库文件”

我不会交叉手指,但我会尝试两件事:

  1. 如果可能的话,将KML文件预处理到第二个SQLite数据库,并使用该数据库在主数据库中导入数据(考虑较低的内存/处理器要求)
  2. 小批量处理导入数据。

HTH

编辑:你可能已经检查过了,但是无论如何:无法打开数据库。