有没有一种方法可以重建Dexie键?

4

我有一个使用Dexie的应用程序。升级到iOS 10.3后,按键查找无法正常工作。(实际上是indexeddb的问题,不仅仅是Dexie的问题)我还在震惊中,但是我已经通过db.table.each(function(p) {})确认数据存在,并且用于键的字段也存在且正确。但是如果我执行 db.table.get(primarykey, function(p) {} 或者 db.table.where("somekey").equals(nonprimarykey).first(function(p) {} 则p为未定义。

我尝试做.db.table.each,然后将每个检索到的对象放回以查看它是否会重建键,在Firefox中可以工作,但在Safari或Chrome中不能工作(仍然无法按键检索)。

我还尝试指定具有相同键结构和空升级的新版本,但这没有任何作用(但我只在Chrome中尝试了一次)。

如果数据库是在安装10.3之后创建的,则一切正常,但我希望我的客户不必删除他们的数据库。

有没有办法在不丢失数据的情况下修复这个问题?

2个回答

3

这似乎是Safari的升级错误,应该在bugs.webkit.org上报告。假设这是一种关键性问题,Safari团队在关键性问题方面非常积极,因此他们很可能会修复它。请务必提交报告!

至于解决方法,我建议重新创建数据库。将数据库复制到新数据库中,删除它,然后复制回来并删除中间副本。我没有验证以下代码,所以您需要进行测试。

function check_and_fix_IOS_10_3_upgrade_issue () {
    return (somehowCheckIfWeNeedToDoThis) ?
        recreateDatabase() : Promise.resolve();
}

function recreateDatabase () {
    copyDatabase("dbName", "dbName_tmp").then(()=>{
        return Dexie.delete("dbName");
    }).then(()=>{
        return copyDatabase("dbName_tmp", "dbName");
    }).then(()=>{
        return Dexie.delete("dbName_tmp");
    });
}

function copyDatabase(fromDbName, toDbName) {
    return new Dexie(fromDbName).open().then(db => {
        let schema = db.tables.reduce((schema, table) => {
            schema[table.name] = [table.schema.primKey.src]
                .concat(table.schema.indexes.map(idx => idx.src))
                .join(',');
        }, {});

        let dbCopy = new Dexie(toDbName);
        dbCopy.version(db.verno).stores(schema);

        return dbCopy.open().then(()=>{
            // dbCopy is now successfully created with same version and schema as source db.
            // Now also copy the data
            return Promise.all(
                db.tables.map(table =>
                    table.toArray().then(rows => dbCopy.table(table.name).bulkAdd(rows))));
        }).finally(()=>{
             db.close();
             dbCopy.close();
        });
    })
}

关于"somehowCheckIfWeNeedToDoThis",我无法确定如何实现。也许需要使用用户代理嗅探+Cookie(在固定后设置持久性Cookie,以便不会一遍又一遍地被重新创建)。也许您会发现更好的解决方案。

然后,在打开数据库之前(或许在应用程序启动之前),您需要执行以下操作:

check_and_fix_IOS_10_3_upgrade_issue()
    .then(()=>app.start())
    .catch(err => {
        // Display error, to user
    });

感谢您的想法和告诉我该在哪里报告这个问题。我同意这是升级中的一个漏洞,但不知道应该在哪里报告它。不幸的是,他们似乎处于宕机或繁忙状态。我会继续尝试。 - Qoregexp
很好你报告了这个问题。我在Dexie上发布了一个问题,以便其他用户确认此错误(https://github.com/dfahlander/Dexie.js/issues/499)。你有WebKit问题的URL吗?我想将Dexie问题链接到它上面。 - David Fahlander

0

我遇到了同样的问题,使用db.js库。在升级时,我的所有应用程序数据都被清除了。

根据我的测试,看起来10.2 -> 10.3升级会清除任何autoIncrement设置为false的表中的数据。在autoIncrement=true表中保存的数据在升级后仍然可以访问。

如果是这种情况,那么这是一个相当严重的错误。Safari的autoIncrement功能存在许多问题,导致我们很多人转而管理自己的ID。

我还没有用vanilla JS测试过这个理论。如果有人想要做,请将您的结果添加到bugs.webkit.org ticket中。


我不知道OS X最近是否有更新,但是在桌面Mac上使用我的应用程序的某个人遇到了相同症状的问题,因此可能不仅仅是iOS。我不知道这两者有多少同步,如果有的话。 - Qoregexp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接