在我們的Android和iOS MVVMCross應用程序中,偶爾會遇到SQLiteException:繁忙異常。SqliteException繁忙的iOS/Android Xamarin MVVMCross
鑑於下面的代碼,我們有幾個存儲庫,每個存儲庫構建下面的一個實例和一個到Sqlite數據庫的關聯連接。想象一下,我們有一個股票庫和一個估值庫,將創建SqliteDataService的兩個實例:SqliteDataService類型爲Stocks,SqliteDataService類型爲Valuations,每個類型都有一個到Sqlite數據庫的連接。
存儲庫上的操作可能在後臺線程上操作,這意味着我們可能會嘗試將庫存與Valuations同時插入數據庫。
現在給每個存儲庫創建自己的SqliteDataService,connectionObject鎖只會保護相同的存儲庫類型不能同時訪問數據庫,而不能保護Stocks和Valuations不能同時訪問數據庫。
我的問題是:
有效期是創建每個存儲庫連接,如果是的話,我們該如何防範SqliteException:忙什麼呢?
有更好的模式嗎?即我們是否應該創建一個非泛型的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);
}
}
您是否解決了這個問題?如果它是固定的,請發表一個答案。 –