gpt4 book ai didi

android - SqliteException 忙 iOS/Android Xamarin MVVMCross

转载 作者:IT王子 更新时间:2023-10-29 06:26:53 25 4
gpt4 key购买 nike

在我们的 Android 和 iOS MVVMCross 应用程序中,我们偶尔会遇到 SQLiteException: busy 异常。

给定下面的代码,我们有几个存储库,每个存储库都构造一个下面的实例和一个到 Sqlite 数据库的关联连接。假设我们有一个 Stocks Repository 和一个 Valuations Repository,将创建两个 SqliteDataService 实例:类型为 Stocks 的 SqliteDataService 和类型为 Valuations 的 SqliteDataService,每个实例都与 Sqlite 数据库连接。

存储库上的操作可能在后台线程上运行,这意味着我们可能会尝试在估值的同时将股票插入数据库。

现在假设每个存储库都创建了自己的 SqliteDataService,connectionObject 锁只会保护相同的存储库类型免于同时访问数据库,而不是保护 Stocks 和 Valuations 免于同时访问数据库。

我的问题是:

为每个存储库创建一个连接是否有效?如果有效,我们如何防止 SqliteException: busy?

还有更好的模式吗?即我们是否应该创建一个跨线程共享相同连接的非通用 SqliteDataService 类?我们已经尝试过了,但在 Android 上我们遇到了致命的异常。

有人为 Xamarin MVVMCross 提供可靠的 Sqlite DAL 模式吗?

public class SqliteDataService<T> : IDataService<T> where T : new()
{
private static object lockObject = new object();

private static object connectionObject = new object();

private static ISQLiteConnection _connection;

private static SqliteDataService<T> _instance;

public SqliteDataService(ISQLiteConnectionFactory connectionFactory, string dbPath)
{
if (_connection == null)
{
_connection = connectionFactory.Create (dbPath);
_connection.CreateTable<T> ();
}
}

public static SqliteDataService<T> GetInstance(ISQLiteConnectionFactory connectionFactory, string dbPath)
{

if (_instance == null)
{
lock (lockObject)
{
_instance = new SqliteDataService<T> (connectionFactory, dbPath);
}
}

return _instance;
}

public void CreateTable<T> ()
{

}

public void Insert(T value)
{
lock (connectionObject) {
_connection.Insert (value, typeof(T));
}
}

public void InsertAll(IEnumerable<T> values)
{
lock (connectionObject) {
_connection.Insert (values, typeof(T));
}
}

public IEnumerable<T> Read(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
return _connection.Table<T> ().Where (predicate);
}
}

public T ReadFirst(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
return Read (predicate).FirstOrDefault ();
}
}

public void Update(T value)
{
lock (connectionObject) {
_connection.Update (value, typeof(T));
}
}

public void Delete(Expression<Func<T, bool>> predicate)
{
lock (connectionObject) {
var valuesToDelete = Read (predicate);

if (valuesToDelete == null)
return;

foreach (var value in valuesToDelete) {
_connection.Delete (value);
}
}

最佳答案

听起来您有几个选择:

  1. 仅实例化一个 SqliteDataService 并将对它的引用传递给您的 Stocks 和 Valuations 对象,这似乎是最明智的,因为它们都在同一个数据库上运行

  2. 实例化一个对象以用作服务外部的锁,并将引用传递给 SqliteDataService 构造函数,以便两个服务共享锁。我相信这会奏效,但我不是锁定方面的专家。

  3. 您可以在 try catch block 中处理 Busy 异常,并迭代一个计数器以对数据库进行最大次数的尝试,每次等待很短,这样您就有很好的连接机会。如果数据库仍然很忙,你仍然会得到异常,这个解决方案是一个相当困惑的解决方案。

  4. 重构 DB 以便将两个区域分开,这可能是不可能的,但值得考虑。

关于android - SqliteException 忙 iOS/Android Xamarin MVVMCross,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29797572/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com