SqliteException ocupado iOS / Android Xamarin MVVMCross

En nuestra aplicación de Android y iOS MVVMCross estamos experimentando SQLiteException ocasional: excepciones ocupadas.

Dado el código siguiente, tenemos varios repositorios cada uno de los cuales construye una instancia de la siguiente y una conexión asociada a la base de datos Sqlite. Imagine que tenemos un Repositorio de Stocks y un Repositorio de Valuaciones, se crearán dos instancias de SqliteDataService: SqliteDataService con tipo Stocks y SqliteDataService con tipos Valuations, cada uno de los cuales tiene una conexión a la base de datos Sqlite.

Las acciones en los repositorios pueden operar en hilos de fondo, lo que significa que podemos intentar insertar Stocks en la base de datos al mismo tiempo que Valuations.

Ahora, dado que cada repositorio crea su propio SqliteDataService, el bloqueo connectionObject sólo protegerá a los mismos tipos de repositorio para que accedan a la base de datos al mismo tiempo en lugar de proteger a Stocks y Valuations de acceder a la base de datos al mismo tiempo.

Mis preguntas son:

¿Es válido crear conexiones por repositorio y, si es así, cómo protegemos contra SqliteException: busy?

¿Hay un patrón mejor? Ie ¿Deberíamos crear una clase SqliteDataService no genérica que comparta la misma conexión a través de subprocesos? Hemos probado esto, pero en Android experimentamos excepciones fatales.

¿Alguien tiene un sólido Sqlite DAL patrón para 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); } } 

Suena como si tuvieras algunas opciones:

  1. Instanciar sólo un único SqliteDataService y pasar una referencia a él a sus valores y Valuaciones objetos, esto parecería más sensato, ya que ambos están operando en el mismo DB

  2. Instanciar un objeto para su uso como bloqueo fuera del servicio y pasar una referencia al constructor SqliteDataService para que el bloqueo se comparta con ambos servicios. Creo que esto funcionaría, pero no soy experto en bloqueo.

  3. Usted podría manejar la excepción Ocupado en un bloque try catch e iterar un contador para hacer un número máximo de intentos contra la base de datos con una corta espera cada vez para que tenga una buena oportunidad de conectarse. Si el DB sigue ocupado, todavía obtendrá la excepción y esta solución es bastante desordenada.

  4. Reestructurar el DB para que las dos áreas están separadas, esto probablemente no es posible pero vale la pena un pensamiento.

  • Xamarin PCL vs. SL confusion
  • Xamarin construir acción de advertencia XA0101
  • Error al depurar aplicaciones Android con Xamarin
  • Pasar datos entre los modelos de vista MvvmCross
  • Manejo adecuado del cambio de configuración
  • Cómo tomar instantánea de montón de Xamarin.Android's Mono VM?
  • La aplicación reanuda los resultados en bloqueo con FormsAppCompatActivity
  • Mono.Data.Sqlite.SqliteConnection.SetConfig lanza una biblioteca utilizada incorrectamente excepción
  • Monodroid - Manejo Haga clic en eventos dentro de las filas ListAdapter
  • Cómo ejecutar código después de un retraso en Xamarin Android
  • Pase objetos personalizados a la siguiente actividad en Xamarin Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.