2014-01-24 2 views
0

Я использую в проекте Windows 8 (js/html) библиотеку SQLite3-WinRT https://github.com/doo/SQLite3-WinRT.
Я создаю функцию, которая вызывается в цикле for. У меня есть эта ошибка:База данных winjs sqlite заблокирована

SQLiteError: 0x800700aa: eachAsync("INSERT INTO home (id, url, cksum)VALUES (16, 'main_page_2.jpg', 'e0d046ca3421a3c2df328b293ad5981a');",) database is locked

Я думаю, что ошибка в том, что я создаю новое подключение к каждой итерации цикла, но я не понимаю другого метода. Кто может мне помочь?

Это функция:

function insertInDB(dbPath, tbName, arrayCol, arrayVal) { 
SQLite3JS.openAsync(dbPath).then(function (db) { 
var query = "INSERT INTO " + tbName; 
var column = " ("; 
var values = "VALUES ("; 
for (var i = 0; i < arrayCol.length; i++) { 
if (i == arrayCol.length - 1) { 
column = column + arrayCol[i] + ")"; 
} else { 
column = column + arrayCol[i] + ", "; 
} 
} 
for (var i = 0; i < arrayVal.length; i++) { 
if (i == arrayCol.length - 1) { 
values = values + arrayVal[i] + ");"; 
} else { 
values = values + arrayVal[i] + ", "; 
} 
} 
query = query + column + values; 
return db.eachAsync(query).done(function() { 
console.log("Ok"); 
db.close(); 
}, 
function (error) { console.log(error); }, 
function (progress) { }); 
}); 
} 

и это цикл, который называют предыдущую функцию:

listHome.forEach(function(value, index, array){ 
var valconfig = new Array(value.id, "'" + value.url + "'", "'" + value.cksum + "'"); 
console.log("id=" + value.id + " url=" + value.url + " ck=" + value.cksum); 

        insertInDB(sqlPath, "home", colconfig, valconfig); 
       })  

ответ

0

Если я правильно читать это, ваш код вызова итерация по списку значений синхронно. listHome.forEach назовет insertInDB за каждый пункт в listHome ... но он не дожидается insertInDB, чтобы вернуться перед следующим звонком в insertInDB.

Внутри insertInDB Вы звоните в SQLite3JS.openAsync и db.eachAsync - оба асинхронных метода. После того, как вы немного изучили SQLite3JS (что выглядит довольно круто), оба этих метода возвращают обещания, где внутри они обращаются к компоненту WinRT. Отличный дизайн.

Так что это то, что, как я подозреваю, происходит: один из асинхронных вызовов в insertInDB помещает блокировку в базу данных. Тем не менее, insertInDB возвращает управление обратно в цикл listHome.forEach, как только, когда он достигает первого вызова асинхронного метода. Если блокировка в базе данных остается некогда forEach переходит к следующему элементу в спискеHome, тогда операция будет пытаться записать в заблокированную базу данных. Отсюда и ошибка.

Я подумаю об этом немного и посмотрю, смогу ли я придумать решение.

- редактировать -

Хорошо, у меня есть решение, которое могло бы работать для вас. Возможно, вы захотите создать класс «DataBaseHelper», который будет помещать в очередь транзакции, которые необходимо сделать в базе данных.

Вот грубый прототип, который я бросил вместе:

[Заменяет цикл Еогеасп]

DBHelper.queueUpdates(listHome); 

[DBHelper определения модуля]

(function() { 

    var _queue; 

    function queueUpdates(array) {   
     _queue = array; 
     scheduleUpdates(); 
    } 

    function scheduleUpdates() { 
     if (_queue.length > 0) { 
      var transaction = _queue.pop(); 
      insertInDB("path", "table", "column", transaction); 
     } 
    } 

    function insertInDB(dbPath, tbName, arrayCol, arrayVal) { 
     return SQLite3JS.openAsync(dbPath).then(function (db) { 

      // Construct your SQL query ... 

      return db.eachAsync(query).done(function() { 
       db.close(); 
       scheduleUpdates(); 
      }, 
      function (error) { console.log(error); }, 
      function (progress) { }); 
     }); 
    } 

    WinJS.Namespace.define("DBHelper", { 
     queueUpdates: queueUpdates 
    }) 
})(); 
+0

В фрагменте кода, не указаны значения для аргументов «dbPath», «arrayCol» в InsertInDB, поэтому я ничего не мог предположить. Я предполагаю, что ваш SQL-запрос работает. «transaction» представляет отдельные элементы из массива listHome. то код, который я разместил, использует рекурсию для перебора значений, проверяя, достиг ли он конца массива перед планированием другой транзакции. –

+0

Я использую ваш код, но запрос вставляет только последнее значение listhome. – user3231894

+0

Я исправляю ошибку. Теперь у меня другая проблема. если я вызвал 2 раза функцию DBHelper.queueUpdates, у меня такая же ошибка, например: DBHelper.queueUpdates (sqlPath, "table1", colconfig, listHome); DBHelper.queueUpdates (sqlPath, "table2", lconfig, listHome); У меня есть база данных ошибок – user3231894

Смежные вопросы