Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

The issue is when you have two different object stores in the same indexeddb, primary key values appear to be "shared" across all stores.

<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>

(Fiddle: http://jsfiddle.net/jonnyknowsbest/4pdp8vxe/)

In iOS8, if you run up the fiddle and click "Add1 data to IndexedDb", then 1000 entries get added to the "customers" table. If you then click "Add2 data to IndexedDb", then 1000 entries get added to the "suppliers" table, but the 1000 from the "customers" is removed.

Has anyone else come across this? Is this part of the IndexedDb specification? Chrome does not seem to have this problem.

EDIT: Found this W3 Org IndexedDB Recommendation: "There can never be multiple records in a given object store with the same key." Apple seem to have applied this at the database level.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
108 views
Welcome To Ask or Share your Answers For Others

1 Answer

I can confirm that iOS8 is definitely buggy here. I tried a few workarounds, but the best I can suggest is a primary key that combines some unique string, like the name of the objectStore, with a number. So for example, given two objectStores called people and notes, I'd store data with keys like so:

people/X notes/X

You can set X manually, or, use the .count() method on the objectStore to find the count and add one. Here is an example:

//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");
    }

}

Note that I specified keyPath of "id" for this OS.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...