5

Macでxamarin studioを使用して、ios用の単純なsqlite駆動型アプリを作成しています。

sqlite ファイルは「個人用」フォルダーに作成され、ビルド間で保持されますが、アプリを実行すると、前のデバッグ セッションで作成したテーブルが消えてしまいますか?

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

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

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

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 が保持されないことです。「File.Exists(dbPath)」は true を返すため、CreateFile は実行されません。データベースが空なのはなぜですか?

4

2 に答える 2

8

これは、iOS シミュレーターでデータベースを保存するために使用したコード スニペットであり、データはアプリのコンパイル間で問題なく保持されるようです。

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

Github から Xamarin の SQLite クラスを確認することもできます: https://github.com/praeclarum/sqlite-net/tree/master/src

上記のクラスの使用方法に関するチュートリアルは次のとおりです。 http://docs.xamarin.com/recipes/ios/data/sqlite/create_a_database_with_sqlitenet

于 2013-05-13T21:46:46.267 に答える
0

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

于 2013-05-14T20:33:31.193 に答える