SQLite-net и SQLite-WinRT одновременно в приложениях среды выполнения Windows

Раньше я использовал библиотеку SQLITE-NET для всех своих задач базы данных sqlite, и она работала хорошо. Но в моем приложении нужно вставить огромное количество данных, и это заняло много времени. Поэтому я решил использовать оболочку SQLITE-WinRT только там, где требуется массовая вставка, поскольку оболочка SQLITE-WinRT, по-видимому, предоставляет такие функции, как подготовка операторов, затем связывание данных и их последующее выполнение, что ускоряет обработку и повышает производительность.

В моем приложении есть много операций CRUD, использующих методы SQLITE-NET, и я оставил все как есть, поскольку сложно полностью переключиться с библиотеки SQLITE-NET на оболочку SQLITE-WinRT.

В моем приложении есть фоновая задача, которая запускает и обрабатывает некоторые вызовы веб-службы и множество операций CRUD, используя только библиотеку SQLITE-NET.

Всякий раз, когда я пытался выполнить массовую вставку с помощью оболочки SQLITE-WinRT с использованием подготовленных операторов, в случае, если фоновая задача выполняется, она всегда выдает исключение Busy в библиотеке SQLITE-NET. Я знаю его причину, фоновый сервис выполняет множество операций CRUD, используя библиотеку SLITE-NET. Таким образом, при массовой вставке с использованием оболочки SQLITE-WinRT выдается исключение Busy, поскольку база данных sqlite уже выполняет множество задач в фоновом режиме с использованием SQLITE-NET.

Итак, мой вопрос, как справиться с этой ситуацией. Пожалуйста, предложите мне несколько идей для обработки таких случаев. Я подумал о двух идеях:

  • Остановка фоновой службы при массовой вставке (в фоновом режиме есть ряд длительных задач, таких как вызов веб-службы и выполнение работы с базой данных SQLite, сразу останавливать фоновую службу может быть не очень хорошей идеей)
  • Закрытие всех соединений SQLITE-NET (хотя и не сработало, как ожидалось)

Любая помощь будет оценена по достоинству. Заранее спасибо.

При массовой вставке я начал так:

 string dbPath = "collection.sqlite";
 var file = await ApplicationData.Current.LocalFolder.GetFileAsync(dbPath);
 var db = new SQLiteWinRT.Database(file);
 await db.OpenAsync(SqliteOpenMode.OpenReadWrite);
 using (var statement = await db.PrepareStatementAsync("INSERT INTO Forms(ServerFormId,FormFileName,FormStatusId,PriorityId) VALUES(?,?,?,?)"))
                {
                    await db.ExecuteStatementAsync("BEGIN TRANSACTION");
                    statement.Reset();
                    statement.BindTextParameterAt(1, "0");
                    statement.BindTextParameterAt(2, formName);
                    statement.BindTextParameterAt(3, formStatusId);
                    statement.BindTextParameterAt(4, priorityId);
                    await statement.StepAsync().AsTask().ConfigureAwait(false);
                }
                await db.ExecuteStatementAsync("COMMIT TRANSACTION");

SQLite-WinRT: https://blogs.msdn.microsoft.com/andy_wigley/2013/11/21/how-to-massively-improve-sqlite-performance-using-sqlwinrt/

SQLite-net: http://www.codeproject.com/Articles/826602/Using-SQLite-as-local-database-with-Universal-Apps


person Kishor Bikram Oli    schedule 20.02.2016    source источник


Ответы (1)


Боюсь, единственный вариант — использовать lock или semaphore перед доступом к базе данных.

Механизм блокировки гарантирует, что только один поток выполняет внутренний блок кода. Другие потоки синхронно ждут.

readonly object sync = new object();

void MyMethod() {
    lock (sync) {
        ...
    }
}

Семафор аналогичен, но внутренний блок кода может быть выполнен максимально n потоками.

Дополнительные сведения о SemaphoreSlim см. в MSDN< /а>.

person Václav Dajbych    schedule 21.02.2016
comment
Спасибо за Ваш ответ. Не могли бы вы подробнее рассказать, как использовать блокировку или семафор? - person Kishor Bikram Oli; 23.02.2016