【问题标题】:Primary Key issue on iOS8 implementation of IndexedDbiOS8 实现 IndexedDb 的主键问题
【发布时间】:2014-11-19 01:54:18
【问题描述】:

问题是当您在同一个 indexeddb 中有两个不同的对象存储时,主键值似乎在所有存储中“共享”。

<body>
    <script type="text/javascript">
        //prefixes of implementation that we want to test
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

//prefixes of window.IDB objects
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange

if (!window.indexedDB) {
    window.alert("Your browser doesn't support a stable version of IndexedDB.")
}


var db;
var request = window.indexedDB.open("newDatabase", 4);

request.onerror = function(event) {
  console.log("error: ");
};

request.onsuccess = function(event) {
  db = request.result;
  console.log("success: "+ db);
};

request.onupgradeneeded = function(event) {
        var db = event.target.result;
        var objectStore = db.createObjectStore("customers", {keyPath: "arseid"});
    var objectStore = db.createObjectStore("test", {keyPath: "id"});
}



function add1() {
        var x = new Date();
    var h1 = x.getHours();
    var m1 = x.getMinutes();
    var s1 = x.getSeconds();
    console.log('starting insert on ' +  h1 + ':' + m1 + ':' + s1);

    var tx = db.transaction(["customers"], "readwrite");
    for (var i = 0; i < 1000; i++) {
        var request = tx.objectStore("customers")
                .put({ arseid: i, name: "Jonathan Smith", email: "jonathan.smith@anemailaddress.com", favourite: "chocolate cake", pet: "rudolph the red nose reindeer", address: "999 letsbe avenue, townton, countyshire" });
    }


    tx.oncomplete = function (e) {
            // Re-render all the todo's
            var x2 = new Date(); 
            var h2 = x2.getHours(); 
            var m2 = x2.getMinutes(); 
            var s2 = x2.getSeconds(); 
               console.log('transaction complete ' + h2 + ':' + m2 + ':' + s2);
        }
}


function add2() {
    //tx 2
    var tx2 = db.transaction(["test"], "readwrite");
    for (var i = 0; i < 1000; i++) {
        var request2 = tx2.objectStore("test")
                .put({ id: i, name: "Robwin Mwengway", email: "jonathan.smith@anemailaddress.com", favourite: "chocolate cake", pet: "rudolph the red nose reindeer", address: "999 letsbe avenue, townton, countyshire" });
    }

    tx2.oncomplete = function (e) {
            var x3 = new Date(); 
            var h3 = x3.getHours(); 
            var m3 = x3.getMinutes(); 
            var s3 = x3.getSeconds(); 
               console.log('transaction complete ' + h3 + ':' + m3 + ':' + s3);
        }
}


    </script>
<button onclick="add1()">Add1 data to indexedDb</button>
<button onclick="add2()">Add2 data to indexedDb</button>
</body>

(小提琴:http://jsfiddle.net/jonnyknowsbest/4pdp8vxe/)

在 iOS8 中,如果您启动小提琴并单击“将 1 数据添加到 IndexedDb”,则会将 1000 个条目添加到“客户”表中。如果您随后单击“将 2 数据添加到 IndexedDb”,则会将 1000 个条目添加到“供应商”表中,但会删除“客户”表中的 1000 个。

还有其他人遇到过这个吗?这是 IndexedDb 规范的一部分吗? Chrome 似乎没有这个问题。

编辑:找到这个W3 Org IndexedDB Recommendation:“在给定的对象存储中永远不可能有多个具有相同键的记录。” Apple 似乎已经在数据库级别应用了这一点。

【问题讨论】:

  • 哇,太糟糕了。我还没有尝试过 iOS 8,但从用户那里得到了一些报告,说我的基于 iDB 的应用程序根本无法在 iOS 8 中运行,这可以解释这一点。我不能说我很惊讶,这符合我的阴谋论stackoverflow.com/a/20110477/786644 :)
  • 天哪。即使你让它指定autoIncreement,它似乎也被打破了。
  • 呃。我试图通过使用一个事务来修复它 - 您可以在一个事务中指定 N 个对象存储。不,会引发错误。
  • 据我所知,您必须指定键,并且必须使它们在每个数据库中都是唯一的。今天打算在一篇博文中写出来。
  • 天哪,是的。以多种方式。我有一个解决方法,我要写博客了。我在 raymondcamden.com。它应该在 30 分钟内启动。

标签: javascript mobile-safari ios8 indexeddb


【解决方案1】:

我遇到了类似的问题,但是我第一次插入对象存储是一个只有用户名和电子邮件的小数组,而第二个对象存储非常大,有几个嵌套的数据数组。

我下面的插入方法会在所有项目上回调成功,但是只有第二个对象存储会正确写入数据库。

当我尝试颠倒写入数据库的顺序时(首先写入大型对象存储项,然后写入用户名/电子邮件),两个对象存储都正确写入,但是主键在两个对象存储之间共享。 飞行员主键:1,2,3,4,5 交流主键:6,7,8...

function insert_GroupRecord(Record, Store){
    //update individual sync record
    var trans = dbGroup.transaction([Store],"readwrite");
    var store = trans.objectStore(Store);
    var request = store.put(Record);
    request.onsuccess = function(e){
        IOS_postMessage({Message:"SyncStatus", status:"Group_Insert "+Store});
    };
    request.onerror = function(e){
        GroupSyncERROR = true;
        //IOS_postMessage({Message:"SyncStatus", status:"GroupSyncFail "+Store});
    };

    request.onupgradeneeded = function(evt){
        var objectStore = evt.currentTarget.result.createObjectStore("AC",{ keyPath: "id", autoIncrement: true });
        objectStore.createIndex("ident", "ident", { unique: true });
        var objectStore2 = evt.currentTarget.result.createObjectStore("Pilots",{ keyPath: "id", autoIncrement: true });
        objectStore2.createIndex("chatname", "chatname", { unique: true });
        console.log("KFM_Group Upgrade Completed");

    };
}

【讨论】:

    【解决方案2】:

    我可以确认 iOS8 在这里肯定有问题。我尝试了一些解决方法,但我能建议的最好的方法是主键,它结合了一些独特的字符串,比如 objectStore 的名称,和一个数字。例如,给定两个名为 people 和 notes 的 objectStore,我将使用如下键存储数据:

    人/X 笔记/X

    您可以手动设置 X,或者使用 objectStore 上的 .count() 方法查找计数并加一。这是一个例子:

    //Define a person
    var person = {
        name:"Ray",
        created:new Date().toString(),
    }
    
    //Perform the add
    db.transaction(["people"],"readwrite").objectStore("people").count().onsuccess = function(event) {
        var total = event.target.result;
        console.log(total);
        person.id = "person/" + (total+1);
    
        var request = db.transaction(["people"],"readwrite").objectStore("people").add(person);
    
        request.onerror = function(e) {
            console.log("Error",e.target.error.name);
            //some type of error handler
        }
    
        request.onsuccess = function(e) {
            console.log("Woot! Did it");
        }
    
    }
    

    请注意,我为此操作系统指定了“id”的 keyPath。

    【讨论】:

    猜你喜欢
    • 2019-05-26
    • 1970-01-01
    • 2014-11-29
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多