这是使用 Xamarin Forms 和 SQLite 建立数据库连接的完美方式吗?

Ala*_*an2 6 c# xamarin xamarin.forms

我有一个应用程序可以在大部分时间工作,但有时会在 5-10 分钟后停止工作。我正在努力找出问题所在,为此我想得到一些反馈,以了解我与应用程序建立数据库连接的方式是否理想。这是我现在所拥有的:

public partial class App : Application
{
    public static DataManager DB { get; } = new DataManager();

public partial class DataManager 
{
    protected static object l = new object();
    protected SQLiteConnection db1;

    public DataManager()
    {
        db1 = DependencyService.Get<ISQLiteDB1>().GetConnection();
        db2.TimeExecution = true;
    }

public interface ISQLiteDB1
{
    SQLiteConnection GetConnection();
}

[assembly: Dependency(typeof(SQLiteDB1_iOS))]
namespace Ja.iOS
{
  public class SQLiteDB1_iOS : ISQLiteDB1 
  {
    public SQLite.SQLiteConnection GetConnection()
    {
       var sqliteFilename = "db1.db3";
       string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
       string libraryPath = Path.Combine(documentsPath, "..", "Library");
       Debug.WriteLine((libraryPath));
       var path = Path.Combine(libraryPath, sqliteFilename);
       if (!File.Exists(path))
       {
          File.Create(path);
       }
       return new SQLite.SQLiteConnection(path);
    }
  }
}  

[assembly: Dependency(typeof(SQLiteDB1_Android))]
namespace Jap.Droid
{
    public class SQLiteDB1_Android :ISQLiteDB1
    {

        public SQLite.SQLiteConnection GetConnection()
        {
            var sqliteFilename = "db1.db3";
            string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var path = Path.Combine(documentsPath, sqliteFilename);
            if (!File.Exists(path))
            {
                File.Create(path);
            }
            return new SQLite.SQLiteConnection(path);
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

我使用此代码执行查询

public partial class DataManager
{

    public void UpdatePhraseSetViewedFalse()
    {
        sql = string.Format("UPDATE Phrase SET Viewed = 0 WHERE Selected = 1");
        App.DB.RunExecute(sql);
    }

public partial class DataManager
{

    private int RunExecute(String s)
    {
            lock (l)
            {
                try
                {
                    rc1 = db2.Execute(s);
                }
                catch (Exception ex)
                {
                    Crashes.TrackError(ex,
                        new Dictionary<string, string> {
                            {"RunExecute", "Exception"},
                            {"sql", s },
                            {"Device Model", DeviceInfo.Model },
                        });
                    throw;
                }
            }
Run Code Online (Sandbox Code Playgroud)

以及用于插入和更新的代码样式:

            db2.Insert(new QuizHistory()
            {
                QuizId = quiz,
                Cards  = (App.viewablePhrases ?? GetViewablePhrases(MO.Quiz)).Count,
                Score = score,
                UtcNow = (int)Math.Truncate(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds),
                Viewed = 1,
                Deck   = Helpers.Deck.GetTitle()
            });
Run Code Online (Sandbox Code Playgroud)

为了减少出现问题的机会,我应该在访问数据库的所有代码周围添加 lock(l) 吗?我应该改变我的连接方式吗?

Ale*_*akh 1

目前尚不清楚应用程序如何停止工作(崩溃、挂起、其他?),但代码似乎有一些危险信号可能会导致:

  1. lock您在从数据库访问数据时使用。虽然语法是正确的,但它可能会导致死锁,并且如果您调用数据访问方法(例如UpdatePhraseSetViewedFalse从 UI 线程调用数据访问方法)(很可能您会这样做),这将是应用程序挂起/崩溃的主要原因。

  2. 您正在手动创建 SQL 查询并执行它们。SQLite在多线程访问时会出现性能问题,因此您可以尝试阅读最佳实践,并更好地使用一些 ORM 和 Wrapper SDK 来正确访问数据库。例如适用于 iOS 的 SQLite.NET适用于 Android 的 SQLite.NET