W naszej aplikacji MVVMCross na Androida i iOS występują sporadyczne wyjątki SQLiteException: ruchliwe wyjątki.SqliteException zajęty iOS/Android Xamarin MVVMCross
Podając poniższy kod, mamy kilka repozytoriów, z których każdy tworzy instancję poniżej i powiązanego połączenia z bazą danych Sqlite. Wyobraźmy sobie, że mamy Repozytorium Zapasów i Repozytorium Wycen, zostaną utworzone dwa wystąpienia SqliteDataService: SqliteDataService z typem Stocks i SqliteDataService z typami Valuations, z których każdy ma połączenie z bazą danych Sqlite.
Akcje w repozytoriach mogą działać na wątkach działających w tle, co oznacza, że możemy próbować wstawiać Zapasy do bazy danych w tym samym czasie co Wyceny.
Teraz, gdy każde repozytorium tworzy własną SqliteDataService, blokada connectionObject chroni tylko te same typy repozytoriów przed dostępem do bazy danych w tym samym czasie, a nie chroni zapasów i wyceny przed dostępem do bazy danych w tym samym czasie.
Moje pytania są następujące:
Czy to ważne, aby stworzyć połączeń na składowiska, a jeśli tak, to w jaki sposób ustrzec się przed SqliteException: zajęty?
Czy istnieje lepszy wzór? Czy powinniśmy utworzyć nietypową klasę SqliteDataService, która ma takie samo połączenie między wątkami? Próbowaliśmy tego, ale w systemie Android doświadczamy fatalnych wyjątków.
Czy ktoś ma stabilny Sqlite DAL dla 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);
}
}
Naprawiłeś to? Opublikuj odpowiedź, jeśli została naprawiona. –