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.
- Cómo utilizar controles Xamarin.Form y controles nativos En la misma página
- Strike html tag no renderizado en EditText con TextFormatted
- Colores de Xamarin que causan errores de compilación
- Random System.ArgumentException: 'jobject' no debe ser IntPtr.Zero
- C # en Android: Xamarin o Unidad?
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); } }
- NDK no se encuentra en la ubicación especificada
- Dispositivos usb android, c # Xamarin
- Xamarin Shared Projects vs Bibliotecas de clases portátiles
- La aplicación no se ejecuta en el emulador de Visual Studio para Android en Visual Studio 2015
- xamarin android webview ya no recupera la página servida localmente con httplistener
- Problemas al implementar la versión de la aplicación Xamarin.Android
- Java Lang UnsupportedClassVersion Error en Xamarin Studio
- Teclado rápidamente se oculta y reaparece en Android usando Xamarin Forms
Suena como si tuvieras algunas opciones:
-
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
-
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.
-
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.
-
Reestructurar el DB para que las dos áreas están separadas, esto probablemente no es posible pero vale la pena un pensamiento.
- Frictionless compartir facebook en Android
- Android se conecta al servidor con certificado autenticado