2013-05-13 19 views
5

Mac上でxamarin studioを使用してios用の簡単なsqlite駆動型アプリケーションを作成しています。xamarin iosを使用したビルド間でデータベースが維持されない

sqliteファイルは "個人用"フォルダに作成され、ビルド間で保持されますが、前回のデバッグセッションで作成したテーブルはなくなっています。

私のコードでは、ファイルが存在することを確認した後、sqliteconnectionを使用して接続し、テーブルを作成し、コマンドオブジェクトからexecutenonqueryメソッドを使用して行を挿入します。同じコンテキストで私は2番目のコマンドオブジェクトを使用してテーブルをクエリできますが、私はデバッガを停止し、私が行ったテーブルを再起動するか?

ファイルを別のフォルダに置く必要がありますか?xamarinまたはiosの設定でテーブルを保持していますか?私は意図的にsqliteで一時テーブルを使用していますか、何が問題になる可能性がありますか?

注:これまでのところ、iphoneシミュレータではxamarinのスターターバージョンとデバッグのみを使用しています。

public class BaseHandler 
{ 
    private static bool DbIsUpToDate { get; set; } 

    const int DB_VERSION = 1; //Created DB 

    const string DB_NAME = "mydb.db3"; 
    protected const string CNN_STRING = "Data Source=" + DB_NAME + ";Version=3"; 

    public BaseHandler() 
    { 
     //No need to validate database more than once on each restart. 
     if (DbIsUpToDate) 
      return; 

     CheckAndCreateDatabase(DB_NAME); 

     int userVersion = GetUserVersion(); 
     UpdateDBToVersion(userVersion); 

     DbIsUpToDate = true; 
    } 

    int GetUserVersion() 
    { 
     int version = 0; 

     using (var cnn = new SqliteConnection(CNN_STRING)) 
     { 
      cnn.Open(); 

      using (var cmd = cnn.CreateCommand()) 
      { 
       cmd.CommandText = "CREATE TABLE UVERSION (VERSION INTEGER);" + 
            "INSERT INTO UVERSION (VERSION) VALUES(1);"; 
       cmd.ExecuteNonQuery(); 
      } 

      using (var cmd = cnn.CreateCommand()) 
      { 
       cmd.CommandText = "SELECT VERSION FROM UVERSION;"; 
       var pragma = cmd.ExecuteScalar(); 
       version = Convert.ToInt32((long)pragma); 
      } 
     } 

     return version; 
    } 


    void UpdateDBToVersion(int userVersion) 
    { 
     //Prepare the sql statements depending on the users current verion 
     var sqls = new List<string>(); 

     if (userVersion < 1) 
     { 
      sqls.Add("CREATE TABLE IF NOT EXISTS MYTABLE (" 
        + " ID INTEGER PRIMARY KEY, " 
        + " NAME TEXT, " 
        + " DESC TEXT " 
        + ");"); 
     } 

     //Execute the update statements 
     using (var cnn = new SqliteConnection(CNN_STRING)) 
     { 
      cnn.Open(); 

      using (var trans = cnn.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)) 
      { 
       foreach(string sql in sqls) 
       { 
        using (var cmd = cnn.CreateCommand()) 
        { 
         cmd.CommandText = sql; 
         cmd.ExecuteNonQuery(); 
        } 
       } 

       trans.Commit(); 

       //SetUserVersion(DB_VERSION); 
      } 

     } 
    } 

    protected string GetDBPath (string dbName) 
    { 
     // get a reference to the documents folder 
     var documents = Environment.GetFolderPath(Environment.SpecialFolder.Personal); 

     // create the db path 
     string db = Path.Combine (documents, dbName); 

     return db; 
    } 

    protected void CheckAndCreateDatabase (string dbName) 
    { 
     var dbPath = GetDBPath(dbName); 

     // determine whether or not the database exists 
     bool dbExists = File.Exists(dbPath); 

     if (!dbExists) 
      SqliteConnection.CreateFile(dbPath); 
    } 
} 

繰り返しますが、私の問題は、私は、デバッガを実行するたびに、それはGetUserVersionを実行しますが、テーブルUVERSIONは、セッション間で永続化されていないことです。 CreateFileが実行されないように、 "File.Exists(dbPath)"がtrueを返します。なぜデータベースは空ですか?

+1

毎回初期化コードが実行されているようです。コードサンプルを投稿できますか? – Jason

答えて

0

は私がconnectiを作成していたことが判明オブジェクトへのフルパスではなくdb-nameを持つCNN_STRINGを使用しています。結論として、ファイルが存在しない場合は接続オブジェクトによってデータベースが作成され、File.Exists(...)は必要ない場合があります。完全なパスが提供されていない場合、一時的なdbにする必要があるかどうかはわかりませんが、そうであるようです。接続オブジェクトの作成を「datasource =」に変更すると、問題が解決されました。

7

これは私がiOSのシミュレータで、私のデータベースを保存するために使用されてきたとのデータがアプリ間持続すると思われるコードスニペットでうまくコンパイルされます。また、SQLiteのクラスをチェックアウトすることができます

string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); 
string libraryPath = Path.Combine (documentsPath, "../Library/"); 
var path = Path.Combine (libraryPath, "MyDatabase.db3"); 

GitHubののオフXamarinは用: https://github.com/praeclarum/sqlite-net/tree/master/src

は、ここで述べたクラスを使用する方法についてのチュートリアルです: http://docs.xamarin.com/recipes/ios/data/sqlite/create_a_database_with_sqlitenet

+0

おそらくnoobの質問ですが、ライブラリパスに "/"文字を使用すると、コードはiosとAndroidの間で移植可能になりますか?おそらくそれはすでにSpecialFolder.Personalに固有のものですか? – Cliffhanger

+1

iOSとAndroidの違いを処理するには、次のような条件付きコンパイラの文を使用できます。http://cl.ly/image/2X1l2b0N002G –

+0

トピックに正確ではありませんが、Androidで問題が発生している場合は、 Xamarinの 'preserve data'オプション:http://forums.xamarin.com/discussion/4878/database-sqlite-net-do-not-persist- between-build-on-monodroid – rufo

関連する問題