2014-01-24 88 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将为listHome中的每个项目调用insertInDB ...但在下一次拨打insertInDB之前,它不会等待insertInDB返回。

Inside insertInDB您已致电SQLite3JS.openAsyncdb.eachAsync - 这两种异步方法。细读了SQLite3JS(看起来很酷)之后,这两种方法都会返回promise,在内部它们会调用WinRT组件。伟大的设计。

所以这是我怀疑正在发生的事情:insertInDB中的一个异步调用会对数据库进行锁定。但是,insertInDB返回控制回listHome.forEach回路尽快,因为它命中第一个异步方法调用。如果数据库上的锁仍然保留一次forEach到达listHome中的下一个项目,那么操作将尝试写入锁定的数据库。因此错误。

我会仔细考虑一下,看看我能否想出一个解决方案。

- 编辑 -

好的,我有一个可能适合您的解决方案。您可能希望创建一个“DataBaseHelper”类,它将排队您需要在数据库中进行的事务。

这里有一个粗略的原型,我扔在一起:

[取代你的foreach循环]

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

在您的代码段,没有指定值在insertInDB中为“dbPath”,“arrayCol”参数,所以我不能假设任何东西,我假设你的SQL查询工作。“transaction”代表listHome数组中的单个项目。查看listHome中的值,我发布的代码使用递归遍历值,在调度另一个事务之前检查它是否到达数组的末尾。 –

+0

我使用你的代码,但查询只插入listhome的最后一个值。 – user3231894

+0

我纠正了错误。现在我有另一个问题。如果我调用2次函数DBHelper.queueUpdates我有同样的错误,例如: DBHelper。queueUpdates(sqlPath,“table1”,colconfig,listHome); DBHelper.queueUpdates(sqlPath,“table2”,lconfig,listHome); 我有错误数据库被锁定 – user3231894