經過大量的搜索並在StackOverflow上閱讀有關SQLite的其他討論後,我找到你,但我絕對找不到解決我的問題的任何解釋,因此它是:SQLite問題「無法打開數據庫文件」
上下文:
我深化發展爲iPad至極的應用程序來處理一些「大」的數據,在多個場合。在其中之一中,我必須從.kml文件(谷歌的xml地理數據)中導入點座標到我的數據庫中,以便稍後用MKMapView重新使用它們,並且在需要顯示特定層。細節:
進口的東西是很容易的:與文件打交道時,我只關心兩個表:- 一種含區的定義和詳細資料:暫時,作爲ID的
integer
和用於命名的text
。 - 其中一個包含兩個用於座標存儲的
real
和一個用於瞭解哪個區域點屬於第一個表的integer
。
只要讀取我的文件,我首先爲新區域創建一個條目,然後在第二個表格中插入點,並在第一個表格中創建最後一個區域的ID ...沒有什麼複雜的!
但是......
- 一種含區的定義和詳細資料:暫時,作爲ID的
問題:
運行正常一段時間後,我得到一個異常從SQLite的有著名的消息「無法打開數據庫文件」,然後將其我無法對數據庫做更多的事情。該例外可以在區域創建或點插入方法中隨機出現。我reflexions:
考慮到這些文件中的無數個點,我懷疑內存或磁盤飽和,但其他部分的我的應用程序丟棄那些點(在我看來)。首先,內存:當發生異常時,應用程序使用大約10或12 MB的RAM。它看起來相當龐大,但是這是由於內存中加載了大約10MB的.kml文件,所以它是可以解釋的。而最重要的是,我的應用程序中的MKMapView事物處理地圖上方的大量高分辨率圖塊,因此導致內存峯值達到20甚至25MB,而不會使iPad崩潰。其次,磁盤:重置我的數據庫並只填充上述兩個表時,發生異常時的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("'", "''") + "'"; }
好,遺憾的小說,我可能已經感謝您閱讀所有的東西,沒有?!無論如何,如果我錯過了可能有用的東西,請告訴我,我會盡快記錄下來。 我希望有人能夠幫助我,無論如何,先謝謝你!
(和我爲我可憐的frenchie的英語道歉)
編輯
我的問題是「解決」了!經過幾次調試,我沒有做出大的修改,但沒有成功,我將代碼放回到發佈它的狀態......現在它可以正常工作。但是,如果有人能夠給我一個可能發生的事情的解釋,我真的很感激!看起來像SQLite的行爲(在iPad上至少 - 從未在任何其他地方使用過)可能在某些時候很模糊...:/
順便說一句,如果有人可以告訴我爲什麼地獄StackOverflow不會讓我開始我的帖子'你好'?我一直認爲禮貌是獲得問題答案的最佳方式! – psycho
你嘗試過Bonjour嗎? – arunkumar