Ich habe also ein relativ einfaches System. Ein mobiler Client erstellt Datensätze in einer SQLite-Datenbank, die ich mit einem Remote-SQL-Server synchronisieren möchte (der mit anderen mobilen Clients gemeinsam genutzt wird) . Wenn ich also einen neuen Eintrag in der SQLite-Tabelle des Telefons erstelle, übertrage ich diese Änderung über eine RESTful-API an meinen Remote-Service. Das Problem, das ich habe, ist, wie ich die Primärschlüssel bestelle, damit die Daten nicht kollidieren (dh ein Datensatz im Telefon hat den gleichen Primärschlüssel wie ein völlig anderer Datensatz auf dem Server). Was ist die übliche "Best Practice" zum Verweisen auf den Datensatz auf dem Client und zum Verweisen auf denselben Datensatz auf dem Server?
sql
web-services
JoeCortopassi
quelle
quelle
Antworten:
In der Regel wird Ihre Datenbank mit
uniqueidentifier
Schlüsseln strukturiert (manchmal als UUIDs oder GUIDs bezeichnet). Sie können sie an zwei Stellen erstellen, ohne realistische Angst vor Kollisionen zu haben.Als Nächstes muss Ihre Mobile-App Faktentabellen vom Server synchronisieren, bevor Sie neue Zeilen erstellen können. Wenn Sie neue Zeilen erstellen, geschieht dies lokal. Wenn Sie erneut synchronisieren, werden dem Server neue Zeilen hinzugefügt. Sie können dasselbe auch mit Aktualisierungen und Löschungen tun.
Zum Verfolgen von Einfügungen benötigen Sie einen erstellten Zeitstempel in Ihren Zeilen. Um Aktualisierungen zu verfolgen, müssen Sie einen LastUpdate-Zeitstempel in Ihren Zeilen verfolgen. Zum Verfolgen von Löschvorgängen benötigen Sie eine Tombstone-Tabelle.
Beachten Sie, dass Sie bei einer Synchronisierung den Zeitversatz zwischen dem Server und dem mobilen Gerät überprüfen und eine Methode zum Lösen von Konflikten benötigen. Einfügungen sind keine große Sache (sie sollten nicht in Konflikt stehen), aber Aktualisierungen können in Konflikt stehen, und ein Löschen kann in Konflikt mit einer Aktualisierung stehen.
Es gibt Frameworks wie Microsoft Sync Framework , die mit solchen Dingen umgehen .
quelle
Ich wette, dass Sie absolut, ohne Frage, keine referenzielle Integrität zwischen den beiden haben können. Erwarten Ihre Benutzer, dass die mobile Anwendung funktioniert, wenn die Verbindung getrennt wird?
Hierfür gibt es zwei Vorgehensweisen:
Eine Möglichkeit besteht darin, "vorläufige" Datensätze auf dem Client zu erstellen. Wenn Sie diese mit dem Server synchronisieren, weist das zentrale System die ID zu. Der Client kann den lokalen Datensatz aktualisieren, um dies widerzuspiegeln.
Zum anderen verteilen Sie die ID-Erstellung so, dass Clients (normalerweise wahrscheinlich) die ID ohne Kollisionen erstellen können.
Wechseln Sie dazu zu UUIDs - es ist ziemlich unwahrscheinlich, dass v4 kollidiert.
Andernfalls sollten Sie etwas in Betracht ziehen, das die eindeutige ID des mobilen Geräts in die Datensatz-ID einfügt. Möglicherweise handelt es sich bei Ihrer Datensatz-ID um eine ID
${imei}-${local sequence number}
, bei der die IMEI die Eindeutigkeit gewährleistet und die lokale Sequenznummer lediglich eine normale sequenzielle Datenbank-ID ist.quelle
Zusätzlich zu Daniel Pittmans Antwort besteht eine Möglichkeit für den Server darin, jedem Client eine eindeutige Client-ID zuzuweisen und die Client-ID zum Teil des Primärschlüssels zu machen.
quelle
Ich habe das gleiche Problem mit einem Projekt, an dem ich arbeite. In meinem Fall bestand die Lösung darin, ein zusätzliches nullwertfähiges Feld in den lokalen Tabellen mit dem Namen remote_id zu erstellen. Wenn Datensätze von der lokalen zur fernen Datenbank synchronisiert werden, wenn remote_id null ist, bedeutet dies, dass diese Zeile nie synchronisiert wurde und eine eindeutige ID zurückgeben muss, die mit der fernen Zeilen-ID übereinstimmt.
In der Client-Anwendung verbinde ich Tabellen mit dem Feld _id, verwende das Feld "Remote-ID" aus der Ferne, um Daten abzurufen, Verknüpfungen durchzuführen usw.
Beispiel vor Ort:
Beispiel aus der Ferne:
Dieses Szenario ohne logischen Code würde zu Fehlern bei der Datenintegrität führen, da die Tabelle client_type möglicherweise weder in der lokalen noch in der entfernten Tabelle mit der tatsächlichen ID übereinstimmt. Daher gibt sie bei jeder Erzeugung einer remote_id ein Signal an die Clientanwendung zurück Wenn Sie aufgefordert werden, das lokale Feld _id zu aktualisieren, wird ein zuvor erstellter Trigger in sqlite ausgelöst, der die betroffenen Tabellen aktualisiert. http://www.sqlite.org/lang_createtrigger.html
1- remote_id wird auf dem Server generiert
2- gibt ein Signal an den Client zurück
3- Der Client aktualisiert das Feld _id und löst einen Trigger aus, der die lokalen Tabellen aktualisiert, die der lokalen _id beitreten
Natürlich verwende ich auch ein last_updated-Feld, um Synchronisationen zu unterstützen und doppelte Synchronisationen zu vermeiden.
quelle