Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Database not persisted between builds with xamarin ios

I'm creating a simple sqlite driven app for ios using xamarin studio on a mac.

The sqlite file is created in the "personal" folder and is persisted between builds but when i run the app the tables i created in the previous debug session is gone?

In my code, after checking that the file exists, i connect using a sqliteconnection and create a table and insert a row with the executenonquery method from the command object. While in the same context i can query the table using a second command object but if i stop the debugger and restart the table i gone?

Should i have the file in a different folder, is it a setting in xamarin or ios to keep the tables? Am i unintentionally using temp tables in sqlite or what could be the problem?

Note: so far i'm only using starter version of xamarin and debugging on iphone simulator.

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);
    }
 }

Again, my problem is that every time I run the debugger it runs GetUserVersion but the table UVERSION is not persisted between sessions. The "File.Exists(dbPath)" returns true so CreateFile is not run. Why is the db empty?

like image 478
Cliffhanger Avatar asked May 13 '13 21:05

Cliffhanger


1 Answers

This is a code snippet I've used to save my databases in the iOS simulator and the data seems to persist between app compiles just fine:

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

You may also want to check out the SQLite class for Xamarin off of Github: https://github.com/praeclarum/sqlite-net/tree/master/src

Here's a tutorial on how to use said class: http://docs.xamarin.com/recipes/ios/data/sqlite/create_a_database_with_sqlitenet

like image 62
Ben Bishop Avatar answered Oct 16 '22 09:10

Ben Bishop