【问题标题】:Database not persisted between builds with xamarin ios数据库在使用 xamarin ios 的构建之间没有持久化
【发布时间】:2013-05-08 01:08:33
【问题描述】:

我正在使用 Mac 上的 xamarin Studio 为 ios 创建一个简单的 sqlite 驱动应用程序。

sqlite 文件是在“个人”文件夹中创建的,并在构建之间保持不变,但是当我运行应用程序时,我在上一个调试会话中创建的表消失了?

在我的代码中,在检查文件是否存在后,我使用 sqliteconnection 进行连接并创建一个表并使用命令对象中的 executenonquery 方法插入一行。虽然在相同的上下文中,我可以使用第二个命令对象查询表,但如果我停止调试器并重新启动表,我就走了?

我应该将文件放在不同的文件夹中,它是 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。为什么数据库是空的?

【问题讨论】:

  • 听起来你的初始化代码每次都在运行。你能发布一个代码示例吗?

标签: ios sqlite xamarin.ios xamarin


【解决方案1】:

这是我用来将我的数据库保存在 iOS 模拟器中的代码 sn-p,并且数据似乎在应用程序编译之间保持正常:

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

【讨论】:

  • 也许是一个菜鸟问题,但使用“/”字符作为库路径,代码可以在 ios 和 android 之间移植吗?也许它已经是 ios 特定的 SpecialFolder.Personal 了?
  • 您可以使用条件编译器语句来处理iOS和Android之间的差异:cl.ly/image/2X1l2b0N002G
  • 不完全是主题,但如果您在 Android 中遇到问题,请务必检查 Xamarin 中的“保留数据”选项:forums.xamarin.com/discussion/4878/…
【解决方案2】:

原来我是使用 CNN_STRING 创建连接对象,它只有 db-name 而不是 db 的完整路径。显然,如果文件不存在,则连接对象会创建数据库,因此可能不需要 File.Exists(...)。如果未提供完整路径,我不确定它是否应该是临时数据库,但似乎是这样。将连接对象的创建更改为“datasource=”解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多