Am 14. September 2017 haben wir eine überarbeitete Fassung unserer Datenschutzrichtlinie veröffentlicht. Wenn Sie video2brain.com weiterhin nutzen, erklären Sie sich mit diesem überarbeiteten Dokument einverstanden. Bitte lesen Sie es deshalb sorgfältig durch.

Cross-Plattform-Apps mit Cordova, Ionic, TypeScript und Visual Studio

Daten mit SQLite abfragen

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Der Trainer zeigt in diesem Film, wie Daten per SQL-Statement aus einer SQLite-Datenbank abgerufen und anschließend auf der Oberfläche angezeigt werden können.
13:05

Transkript

In meinem Angular-Service speichere ich bereits Daten in der Datenbank, hier in der SQLite-Datenbank, über ein INSERT-Statement, aber Speichern ist natürlich relativ uninteressant, wenn man die Daten nicht auch wieder liest. Und bisher werden die Daten eben nicht aus der Datenbank gelesen. sondern es werden einfach die Daten, die ich in meinem Array hier oben habe, zurückgegeben. Ich werde also jetzt damit anfangen, dass ich zum einen die Funktion "getSavedItems" überarbeite, und "getTotal". Ich fange einmal mit "Total" an. Was ich machen muss, um eine Summe zurückzugeben aus einer Tabelle, ist, dass ich ein SQL-Statement schreibe. Und dieses SQL-Statement, das ruft die Aggregatfunktion "sum" auf. Ich summiere hier also den Preis, gebe dem Ganzen einen Alias, und definiere noch meine Tabelle, das ist "savedItems". Und jetzt könnte ich dieses ausführen, indem ich sage: "this.$cordovaSQLite.execute", und dann "this.db", und anschließend das SQL-Statement. Der Punkt ist nun: "execute" selber gibt nicht zurück, denn "execute" ist asynchron. Heißt also: Ich muss hier "then" schreiben, und habe jetzt hier eine Funktion Und diese Funktion, die bekommt das result zurück. Das ist wieder vom Typ "any". Und jetzt kann ich hier Folgendes machen. Ich bekomme immer genau eine Zeile zurück, nämlich entweder mit dem Wert "null", wenn es noch gar nichts gab, oder halt mit einem numerischen Wert. Und jetzt könnte ich hier natürlich sagen: "return res.rows", und dann "item(0)". Das hier ist also die Zeile an der Position "0", also die erste Zeile. Und hier möchte ich den Wert der Spalte "total" zurückgeben, oder, wenn es Null ist, dann gebe ich einfach "0" zurück. Das Problem ist: Das hier wird leider nicht funktionieren. Das wird deswegen nicht funktionieren, weil, dadurch, dass diese Methode hier asynchron ist, sie im Endeffekt aufgerufen wird, dann ist meine "getTotal"-Funktion vorbei, und erst dann wird das hier aufgerufen. Wie können wir jetzt diesem asynchronen Problem entgegentreten? Naja, indem wir unsere Methode "getTotal" auch asynchron machen. Ich sage also: Das ist nicht mehr vom Typ "number", sondern vom Typ "ng.IPromise". Mein "Promise", das ist das Versprechen, dass wir zurückrufen werden. Und zwar, wir werden zurückrufen mit einer Nummer. Jetzt schaut es so aus, dass ich hier bereits ein "Promise" habe. Und das kann ich jetzt einfach zurückgeben. Ich sage jetzt "return" und gebe genau dieses "Promise" zurück. Und dieses "Promise", wenn das dann später ausgelöst wird, das wird dann den Wert hier zurückgeben. Jetzt muss ich meine Schnittstelle noch ändern, denn aktuell sagt mein Interface, dass ich hier eben einen number-Wert zurückgebe, aber das natürlich jetzt ein "IPromise" vom Typ "number". Und jetzt verschwindet auch dieser Fehler hier. Zum Aufruf muss ich jetzt im Endeffekt wie folgt vorgehen. Ich gehe einmal in meinen Home-Controller. Und Sie sehen schon, dass hier Einiges rot ist. Und das liegt einfach daran, dass ich jetzt dieses "getTotal" asynchron aufrufen muss. Ich sage also ".then", und jetzt weiß ich im Endeffekt, dass ich einen numerischen Wert zurückbekomme. Der heißt "total". Und dann nutze ich hier so einen Lambda-Ausdruck. Das geht sehr elegant. Und hier kann ich dann schreiben: "this.totalSaved" ist gleich "total". Warum nutze ich hier einen Lambda-Ausdruck? Das hat einen ganz einfachen Grund. Ich hätte hier auch eine anonyme Funktion schreiben können. Und ich zeige Ihnen mal, wie das ausgesehen hätte. Ich hätte also sowas hier schreiben können: "getTotal().then (function (total)" und dann den gleichen Code, "this.totalSaved", und Sie sehen schon, die IntelliSense klappt nicht mehr. Warum klappt die IntelliSense nicht mehr? Die IntelliSense klappt nicht mehr, weil in dem Moment, wo ich hier eine anonyme Funktion benutze, das "this" sich leider nicht mehr auf meine Klasse bezieht, sondern auf diese Funktion. Und diese Funktion hat kein Feld "totalSaved". Heißt: Ich müsste in irgendeiner Art und Weise eine Möglichkeit schaffen, wieder einen Verweis auf diese Klasse zu holen. Und unter JavaScript macht man da häufig diese Tricks mit "var", "that" gleich "this", und Ähnliches. Haben Sie bestimmt schonmal gesehen. Brauche ich unter C-Sharp nicht. Ich nehme einfach einen Lambda-Ausdruck. Und das funktioniert, indem ich "function" wegnehme, und dann hier so ein Pfeilchen dahin schreibe. Darum nennt man das auch häufig "arrow function". Und schauen Sie mal: Jetzt bekomme ich auch wieder IntelliSense an der Stelle hier. Das ist also der Code, den wir brauchen, um die Summe zu berechnen. Ja, den haben wir jetzt also hier unten gesehen. Was wir dann ja noch haben, ist der Fall, dass wir hier unsere savedItems zurückgeben. Und wie gehen wir hierzu vor? Hierzu brauche ich auch wieder ein SQL-Statement. Und zwar ist es diesmal das folgende Statement. Das ist diesmal "SELECT id, description price, date from savedItems". Und wenn das dann soweit ist, dann möchten wir Folgendes machen. Ich bekomme hier wieder mein "result" zurück, vom Typ "any", packe hier eine anonyme Funktion herein, und hier darf ich das natürlich nicht hinter dem SQL-Statement schreiben. Das ist ja großer Quatsch. Ich muss das ja stattdessen an einem SQL-Aufruf machen. Also schreibe ich: "this.$cordovaSQLite.execute(db, sql)". Und das ist natürlich "this.db". Und hier kommt das "then" hin. So. Heißt: Ich habe jetzt hier mein SQL-Statement geschrieben. Ich habe jetzt hier meine Rückruf-Funktion. Und jetzt kann ich hier die Anzahl der Einträge holen. Ich sage also: "var count" vom Typen "number". Und das ist gleich "res" für "result" ".rows.count". So. Und jetzt weiß ich also, wieviele Zeilen zurückgekommen sind. Und jetzt mache ich einfach eine Schleife, also "for(var i = 0", "i < count" und "i ++". Und innerhalb dieser Schleife werde ich mir jetzt wieder so ein Item erzeugen, sage also: "var item" ist gleich "new SavedItem". Und jetzt übergebe ich hier an der Stelle von meinem result aus der aktuellen Zeile einen Wert, aber da hole ich mir eine kurze, temporäre Tabelle. Ich sage einfach: "row" ist gleich "res.rows.item" von "i". Dann muss ich nicht immer jedes Mal diesen Aufruf hierin haben, sondern kann einfach schreiben: "row.description" und "row.price". Dann sage ich noch: "item.date" ist gleich "new Date", und "item.date.setTime". Und hier übergebe ich jetzt "row.date". Das war die Geschichte, dass das Ganze numerisch gespeichert wird in der Datenbank. Ich brauche jetzt hier zuerst ein initialisiertes Datum an dem Objekt. Dann kann ich hier "setTime" aufrufen, diesen numerischen Wert übergeben, und dann habe ich wieder das korrekte Datum. Zu guter Letzt sage ich: "savedItems.push" "(item)". Und hier schaut es jetzt wie folgt aus. Wenn ich jetzt hier wieder über "this" "savedItems" zurückgeben möchte, würde das wieder nicht gehen, da ich hier eine asynchrone Funktion habe. Und im Endeffekt möchte ich auch gar nicht mehr mit dieser savedItems-Variablen hier oben arbeiten. Stattdessen werde ich die jetzt einfach löschen. Und die werde ich dann auch hier löschen, und hier unten. Die brauchen wir nämlich gar nicht mehr, sondern stattdessen werde ich jetzt hingehen und auch, hier lösche ich es auch noch, im Konstruktor, stattdessen werde ich hingehen und diese Funktion "getSavedItems" jetzt vom Typ "IPromise" vom Typ "Array" von "SavedItem" machen. Heißt also: Ich sage, dass diese Funktion vom Typ "ng.IPromise" vom Typ "Array" von "SavedItem" ist. Und dann werde ich mir hier einfach noch eine Variable "savedItems" definieren. Ich sage: "var savedItems" ist gleich "new Array" vom Typ "SavedItem". Und zu diesem Array füge ich hier munter hinzu. Ich hätte das sogar noch tiefer erzeugen können, nämlich hier erst, in dem Callback. Und dann gebe ich nach der Schleife dieses Array zurück. Visual Studio ist gerade ein wenig unglücklich. Und dass Visual Studio unglücklich ist, liegt daran, dass die Signaturen nicht mehr übereinstimmen. Und die stimmen natürlich nicht mehr überein, weil ich hier oben sage, dass ich hier ein Array von "SavedItem" zurückgebe, in der Schnittstelle, aber es ist ein "Promise" von einem Array von "SavedItems". So. Und dann muss ich hier diesen "Promise" auch zurückgeben. Und dann ist mein Code hier entsprechend in Ordnung. Im Controller muss ich nun noch etwas ändern, allerdings nicht im Home-Controller, sondern in diesem SavedItemsController. Hier habe ich aktuell direkt die Eigenschaft "savedItems" über dieser Methode hier gefüllt. Und das Ganze muss ich jetzt halt eben asynchron machen, indem ich hier sage "then((savedItems", und hier auch wieder als Lambda-Ausdruck, im Endeffekt wegen des "this"-Problems. Und jetzt kann ich hier sagen: "this.savedItems" ist gleich "savedItems". So, und bevor ich das Ganze jetzt starte, muss ich noch eine Kleinigkeit ändern. Und zwar ist mir gerade noch eingefallen: Ich habe hier im SavedItemsService eben die Eigenschaft "count" genutzt, aber es müsste eigentlich "length" heißen. Das ist immer ein bisschen schade. Dadurch, dass wir hier keine IntelliSense haben, bekommt man das halt im Zweifelsfall gar nicht mit. Wenn ich die Anwendung jetzt starte, dann sollte ich aber in der Lage sein, dass ich Einträge speichern kann und diese auch wieder laden kann. So, ich warte einmal, bis das im Emulator ist. Ich führe ihn hier schonmal hoch. So, und ich spare mir mal ein Steak für 12,49. Und wenn ich jetzt auf die Details gehe, dann sehe ich hier, dass ich mir einen Burger, einen Schokoriegel, ein Steak gespart habe. Das hier kommt aus zwei vorherigen Tests. Und wenn ich jetzt die Anwendung einmal beende, und danach hier über den App-Launcher neu starte, dann sehen wir, dass diese drei Einträge auch immer noch da sind. Bedeutet also: Das Speichern von Daten in einer SQLite-Datenbank, das war gar nicht einmal so schwierig. Im Endeffekt mussten wir das SQLite-Plug-In hinzufügen, wir mussten SQL-Statements zum Einfügen speichern, wir mussten SQL-Abfragen zum Laden speichern, wie wir das jetzt hier in diesem Film gemacht haben, und wir mussten dafür sorgen, vor allem, dass unsere Rückgabetypen auf einmal vom Typ "Promise" waren, weil wir eben hier an der Stelle asynchron arbeiten.

Cross-Plattform-Apps mit Cordova, Ionic, TypeScript und Visual Studio

Steigen Sie in die App-Programmierung ein und kombinieren Sie die praktischen Tools.

2 Std. 45 min (23 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Exklusiv für Abo-Kunden
Erscheinungsdatum:14.11.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!