Nella nostra app MVVMCross per Android e iOS stiamo riscontrando occasionalmente SQLiteException: eccezioni occupate.SqliteException occupato iOS/Android Xamarin MVVMCross
Dato il codice di seguito, abbiamo diversi repository ciascuno dei quali costruisce un'istanza di seguito e una connessione associata al database Sqlite. Immaginiamo di avere un deposito di titoli e un repository di valute, verranno create due istanze di SqliteDataService: SqliteDataService con tipo Stocks e SqliteDataService con tipi di valutazioni, ognuna delle quali ha una connessione al database Sqlite.
Le azioni sui repository possono operare su thread in background, il che significa che possiamo tentare di inserire azioni nel database contemporaneamente alle valutazioni.
Ora che ogni repository crea il proprio SqliteDataService, il blocco connectionObject protegge solo gli stessi tipi di repository dall'accesso al database allo stesso tempo anziché proteggere Stock e Valori dall'accesso al database nello stesso momento.
Le mie domande sono:
E 'valido per creare una connessioni per repository e se sì, come possiamo evitare il rischio di SqliteException: occupato?
Esiste uno schema migliore? cioè dovremmo creare una classe SqliteDataService non generica che condivide la stessa connessione tra thread? Abbiamo provato questo, ma su Android sperimentiamo eccezioni fatali.
Qualcuno ha un modello DAL solido Sqlite per Xamarin MVVMCross?
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);
}
}
Hai risolto il problema? Si prega di inviare una risposta se è stato risolto. –