1

将 IndexedDB shim 用于 Web SQL 时,我无法更新记录:https ://github.com/axemclion/IndexedDBShim

我也在使用 IDBWrapper:https ://github.com/jensarps/IDBWrapper

尽管我使用了这些库,但我相信我的问题可能仍然相关,并且可能仍会得到适当的建议,因为它可能仅与 IndexedDB 和 Web SQL 的一般用法有关

我正在使用内联键实现 IndexedDB 存储。

_store = new IDBStore({
    storeName: 'person',
    keyPath: 'PersonId',
    autoIncrement: true,
    onStoreReady: _loadPersons
});

当我将对象保存到商店时...

_store.put(person, _loadPersons);

...它将生成一个自动递增的键,然后将该键值自动存储在以“keyPath”属性命名的对象上,在本例中为PersonId

这很好用。如果我检查 Chrome 中的 IndexedDB 存储,则有 2 列。键(键路径:'PersonId')和值(包含对象)。

如果我想更新同一个对象,我只需确保它包含一个名为PersonId的属性,并且具有与我要保存的键相同的值,并且它会更新。

但是,当使用保存到 Web SQL 的 IndexedDB shim 时(例如,在 Safari for Windows 或移动浏览器中),当我加载对象时,它们根本不包含PersonId属性。

供参考,_loadPersons回调如下:

_loadPersons = function () {
    _store.getAll(_setPersons);
};

如果我在 Safari 中检查 Web SQL 存储,则有 3 列,key(格式为 1-0、1-1、1-2)、inc(1、2、3)和 value(包含 JSON对象的字符串,缺少PersonId属性。

我不确定内联键功能在 IndexedDB 中是如何工作的,但似乎无论它做什么,它都不会在 Web SQL 中发生。

使用这种方法时,我应该如何引用我想要更新的对象?

我应该只使用外键吗?

是否有其他人实现了 IndexedDB -> Web SQL 结构,如果有,他们使用了哪些库,是否遇到过这个问题?

更新:

我查看了使用 IndexedDB polyfill 的 Indexed DB JQuery 插件示例背后的代码:http: //nparashuram.com/jquery-indexeddb/example/。然而,这个例子中所有的项目都已经有了一个“itemId”,并且它没有任何添加新项目的逻辑,只是将现有项目移动到不同的地方(购物车、愿望清单),所以我只能假设这种方法是一种“外键”方法。

更新 2:

我解决我的情况的方式,使我能够使用 IndexedDBShim 和 IDBWrapper,详细说明如下。然而,更好的解决方案可能是放弃这两个库并尝试其他方法。

4

4 回答 4

2

你有没有尝试过我自己的开源库https://bitbucket.org/ytkyaw/ydn-db/wiki/Home它具有从 WebSQL 到 IndexedDB 的完整填充,包括 inline/outline/autoIncrement/compound/multiEntry 键。还有qunit 测试

编辑,附加答案:

如果您使用自动增量内联键,并且您没有手动将时间戳存储在对象上,那么 Web SQL 会知道要更新哪个对象吗?

虽然使用了 autoIncrement 内联键并且记录值没有主键,但它被视为一个新对象(并且确实如此)。注意:Sqlite 也有自增数字主键的概念。

每次刷新演示时,它看起来像在 Web SQL 中创建一个新商店?

没有。如果在页面刷新时创建了新存储,则它不是数据库。

于 2013-10-15T14:28:44.403 回答
1

我在更新对象时遇到了同样的问题。使用内联键无法做到这一点。所以,我改用外键来解决这个问题。我正在使用Jquery IndexedDB 插件插件和IndexedDB Shim的组合来支持所有主要浏览器。

于 2013-10-16T07:10:48.320 回答
1

我解决这个问题的方法是:

  1. 在创建 IDBStore 时始终将其设置keyPath为。"key"这是为了考虑到 IndexedDB Shim 使用调用的属性key来引用 WebSQL 数据库中每条记录的索引这一事实。

  2. 我不得不在 IDBWrapper 代码中添加一个子句:

      // cope with WebSQL implementation, keyPath must always be "key" for this to work.
      if (!cursor.primaryKey) {
        cursor.value.key = cursor.key;
      }
    

进入_getAllCursor如图所示的函数(我的第 682 行):

_getAllCursor: function (getAllTransaction, store, onSuccess, onError) {
  var all = [],
      hasSuccess = false,
      result = null;

  getAllTransaction.oncomplete = function () {
    var callback = hasSuccess ? onSuccess : onError;
    callback(result);
  };
  getAllTransaction.onabort = onError;
  getAllTransaction.onerror = onError;

  var cursorRequest = store.openCursor();
  cursorRequest.onsuccess = function (event) {
    var cursor = event.target.result;
    if (cursor) {
      // cope with WebSQL implementation, keyPath must always be key for this to work.
      if (!cursor.primaryKey) {
        cursor.value.key = cursor.key;
      }
      all.push(cursor.value);
      cursor['continue']();
    }
    else {
      hasSuccess = true;
      result = all;
    }
  };
  cursorRequest.onError = onError;
},

基本上这样做是,如果光标上没有primaryKey,通过Chrome和Safari的测试,这似乎表明代码在WebSQL环境中工作。可能有更可靠的方法来检测缺乏 IDB 支持,但这对我来说效果很好。因此,在 中if,只需将光标的 'key' 属性设置为值,这样当它最终保存到 WebSQL 时,它就会在那里有正确的索引。

但是,因为我没有时间测试他的库并转换到它,而且他非常有帮助,所以我打算让 Kyaw Tun 从怀疑中受益并接受他的回答,尤其是 IDBWrapper 和 IndexedDBShim (根据 GemK 的说法,JQuery IndexedDB 插件和 IndexedDBShim)在使用内联键时似乎不能一起工作。可以说拥有 1 个依赖库而不是 2 个更好。

更新

在使用这种方法的过程中,我确实遇到了一些问题,其中之一是“这是如何工作的?” 情景。

就在我准备删除 IndexedDBShim 和 IDBWrapper 并替换为 ydn-db 时,我在 Safari 中又看了一遍。

如前所述,我不知道这是如何工作的,但在

IDBOjectStore.prototype.put在 IndexedDBShim.js 的第 1090 行(对我来说),密钥未定义,然后从未在更新中使用。

所以我不得不添加

if (key === undefined && value.key !== undefined) {
  key = value.key;
}

更新 2

真的,现在就忽略这个帖子,看起来 IDBShim 将被修复,我相信这将是一个更好的解决方案。但是,此解决方案确实存在另一个问题。检查cursor.primaryKey不是确定的,有时我发现它确实包含那里的关键值。所以cursor.value.key无论如何都要设置。

更新 3

万一有人没有注意到我之前的警告,请忽略这一切。如果您手动设置密钥,它将失败,在我的情况下是静默的,因为如果密钥已设置并且 keypath 也有一个值,WebSQL 无法确定您是否需要内联键(即您定义的键路径)或外联键(即你实际上提供了一个键值,所以大概你不想自动递增)。这是一种误解,认为要更新记录,您需要在对象值之外提供键,只要您保存的对象值具有以键路径字符串命名的属性,包含正确的键,就足够了。

说到这里,为什么我最初在第一个 UPDATE 中详细说明了更改?因为偶尔会添加重复记录而不是更新。

真正的问题是,对我来说,在第 1003 行。主键是从对象中提取的,然后使用!. 对我来说,在某些浏览器中,第一个密钥生成为0. 这会使评估失败,因此 WebSQL 会生成一个新的自动增量键。

我变了:

var primaryKey = eval("value['" + props.keyPath + "']");
if (!primaryKey) {
    if (props.autoInc === "true") {
        getNextAutoIncKey();
    }
    else {
        idbModules.util.throwDOMException(0, "Data Error - Could not eval key from keyPath");
    }
}
else {
    callback(primaryKey);
}

至:

var primaryKey = eval("value['" + props.keyPath + "']");
if (primaryKey === undefined) {
    if (props.autoInc === "true") {
        getNextAutoIncKey();
    }
    else {
        idbModules.util.throwDOMException(0, "Data Error - Could not eval key from keyPath");
    }
}
else {
    callback(primaryKey);
}
于 2013-11-04T09:47:02.630 回答
1

我今天遇到了同样的问题。我已经修补了垫片以将自动生成的 id 包含在记录中。我已在https://github.com/axemclion/IndexedDBShim/issues/122将我的补丁添加到第 122 期

于 2014-05-01T22:21:42.247 回答