Xamarin.Forms 应用程序 - SQLite 事务卡在打开状态?

问题描述 投票:0回答:0

我正在开发适用于 Android、iOS 和 UWP 的跨平台 Xamarin.Forms 应用程序。该应用程序将数据存储在 SQLite 数据库中,并使用 sqlite-net-pcl NuGet 包作为利用 SQLite 存储的库 - https://github.com/praeclarum/sqlite-net。目前它使用的是这个包的 1.7.335 版本。我正在尝试找出是否有人遇到过与我注意到的问题类似的问题,并尝试收集有关如何进行改进以防止此问题发生的想法。

本应用是多线程的,所以应用使用的SQLite数据库连接需要支持。这是将打开与数据库的连接的代码:

private const SOF OpenFlags = SOF.ReadWrite | SOF.Create | SOF.FullMutex | SOF.SharedCache;

public SQLiteConnectionString GetConnectionString(string path)
    => new SQLiteConnectionString(path, true, null);

public SQLiteConnection GetConnection(string path)
{
    var connStr = GetConnectionString(path);
    return new SQLiteConnection(connStr.DatabasePath, OpenFlags, connStr.StoreDateTimeAsTicks);
}

public SQLiteAsyncConnection GetAsyncConnection(string path)
{
    var connStr = GetConnectionString(path);
    return new SQLiteAsyncConnection(connStr.DatabasePath, OpenFlags, connStr.StoreDateTimeAsTicks);
}

我注意到的问题是,SQLite 事务似乎没有明显原因间歇性地保持打开状态。在代码中,没有调用 BeginTransaction() 来显式开始事务,也没有调用 Commit() 来显式保存数据。相反,每当需要在事务中处理某些数据库操作时,代码就会调用 SQLiteAsyncConnection.RunInTransactionAsync()。代码中还有一些地方调用 SQLiteAsyncConnection.InsertAllAsync() 或 SQLiteAsyncConnection.UpdateAllAsync() 时没有为可选的 runInTransaction 参数指定值。此参数默认为 true,因此一些交易也将因此开始。

这种情况的发生是随机的,没有一套好的复制步骤可以遵循以使其发生。如果确实发生了,我注意到应用程序的错误日志记录会报告此类错误,并且会不断报告这些错误,直到应用程序关闭并重新启动,或者直到使用 Rollback() 方法显式回滚事务。

SQLite.SQLiteException: cannot start a transaction within a transaction (this will happen when RunInTransactionAsync is called)
at
SQLiteCommand.ExecuteNonQuery ()
SQLiteConnection.Execute (System.String query, System.Object[] args)
SQLiteConnection.BeginTransaction ()
SQLiteAsyncConnection+<>c__DisplayClass80_0.<RunInTransactionAsync>b__0 (SQLite.SQLiteConnectionWithLock conn)
SQLiteAsyncConnection+<>c__DisplayClass34_0`1[T].<TransactAsync>b__0 ()

System.ArgumentException: savePoint is not valid, and should be the result of a call to SaveTransactionPoint. Parameter name: savePoint (this will happen when InsertAllAsync is called)
at
SQLiteConnection.DoSavePointExecute (System.String savepoint, System.String cmd)
SQLiteConnection.Release (System.String savepoint)
SQLiteConnection.RunInTransaction (System.Action action)
SQLiteConnection.InsertAll (System.Collections.IEnumerable objects, System.Boolean runInTransaction)
SQLiteAsyncConnection+<>c__DisplayClass77_0.<InsertAllAsync>b__0 (SQLite.SQLiteConnectionWithLock conn)
SQLiteAsyncConnection+<>c__DisplayClass33_0`1[T].<WriteAsync>b__0 ()

有没有人遇到过这样的问题?处理这种情况以确保在事务处于活动状态时可能已保存的数据不会丢失的最佳方法是什么?有没有一种编程方式可以用来查看是否有一个进程或查询使事务的存活时间比预期的长?或者也许是一种编程方式来查看对数据库进行了哪些未保存的更改,如果出于任何原因必须回滚事务,这些更改可用于尝试保留更改?尝试在代码中的某处调用 Commit 以保存更改是否安全(如果调用 Commit 导致异常,则调用 Rollback)还是可能导致数据损坏?我知道这些是非常笼统的问题,但我只是在寻找一些指导,了解哪些选项值得研究,因为它与这样的问题(如果有的话)有关。

提前感谢您的帮助。

sqlite xamarin.forms transactions cross-platform
© www.soinside.com 2019 - 2024. All rights reserved.