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.

  • Convertir Xamarin.Forms.Color a color específico de la plataforma
  • Cómo configurar la orientación ContentPage en Xamarin.Forms
  • Operador '! =' No se puede aplicar a los operandos de tipo 'Tarea' e 'int'
  • ¿El oyente Scrollview no está trabajando en Xamarin para Android?
  • Cómo reducir el tamaño del paquete
  • ¿Por qué tomar una aplicación vacía de Xamarin Android alrededor de 10mb de espacio?
  • Xamarin tiempo de ejecución vs Dalvik
  • NotSupportedException No se pudo activar JNI Handle - MvvmCross
  • En android SetText sólo toma resId
  • NullReferenceException en modo Release de la aplicación Xamarin
  • Xamarin Android Exception causa "Frame no en el módulo"
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.