Подтвердить что ты не робот

Первичная ключевая проблема при внедрении iOS8 IndexedDb

Проблема заключается в том, что у вас есть два разных хранилища объектов в одном индексеdeddb, значения первичного ключа отображаются как "общие" для всех магазинов.

<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: "[email protected]", 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: "[email protected]", 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/)

В iOS8, если вы запускаете скрипку и нажимаете "Add1 data to IndexedDb", то 1000 записей добавляются в таблицу "клиенты". Если вы затем щелкните "Add2 data to IndexedDb", то 1000 записей добавляются в таблицу "Поставщики", но 1000 из "клиентов" удаляется.

Кто-нибудь еще сталкивался с этим? Является ли эта часть спецификации IndexedDb? У Chrome, похоже, нет этой проблемы.

EDIT: Найденный Рекомендация W3 Org IndexedDB: "В одном хранилище объектов никогда не может быть нескольких записей с одним и тем же ключом". Apple, похоже, применила это на уровне базы данных.

4b9b3361

Ответ 1

Я могу подтвердить, что iOS8 определенно глючит здесь. Я пробовал несколько обходных решений, но лучшее, что я могу предложить, это первичный ключ, который объединяет некоторую уникальную строку, такую ​​как имя objectStore, с номером. Например, для двух объектов, называемых людьми и заметками, я бы хранил данные с такими ключами:

люди/X примечания /X

Вы можете установить X вручную или использовать метод .count() на объектеStore, чтобы найти счетчик и добавить его. Вот пример:

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

}

Обратите внимание, что я указал keyPath для "id" для этой ОС.

Ответ 2

У меня была аналогичная проблема, однако моя первая вставка в объект-магазин была небольшим массивом с просто именем пользователя и электронной почтой, а второй объект-хранилище был очень большим с несколькими вложенными массивами данных.

Мой метод вставки, приведенный ниже, вызовет успешное выполнение всех элементов, но только второе хранилище объектов будет записано в db правильно.

Когда я попытался изменить порядок, который я писал в базу данных (сначала записывая объекты большого объекта объекта и имя пользователя/электронной почты), оба объекта были написаны правильно, но первичные ключи были разделены между двумя хранилищами объектов. Пилоты Первичный ключ: 1,2,3,4,5 Первичный ключ AC: 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");

    };
}