Eine DatasetOnly-Anwendung ist dieselbe (nicht nur die gleiche) Anwendung wie eine Db-Anwendung: Man baut auf demselben typisierten Dataset auf - nur Laden/Speichern, die "Persistirung" ist wesentlich komplizierter:
(Link:) Persistierung Datenbank <-> typisiertes Dataset
Die komplizierte Persistierung ist - wenn richtig gemacht - der ganze Unterschied.
Obiger Link zeigt den wohl leichtesten Weg, es richtig zu machen, aber leider kursieren tausende von (einfacheren) Tutorials, die es falsch aufziehen.
Und fängt man es erst falsch an, so erhält man vlt. auch lauffähigen Code, und mit Zusatz-Aufwand auch (Link:) injection-sicher aber man verbaut sich zwangsläufig alle Möglichkeiten designergestützten Databindings. Also alles in (Link:) vier Views-Videos gezeigte ist unerreichbar, sobald man erstmal anfängt mit
DbConnection
, DbDataReader
, DbDataAdapter
, DbCommand
herumzuwursteln - selbst wenn lauffähig!Lauffähigkeit des Wurstel-Ansatzes ist im Grunde der Worst Case, denn darauf aufbauende Anwendungen sind buggy, unergonomisch, unperformant und schlicht unwartbar, lassen SQL-Injection zu und stürzen ab, wenn auf englisch- oder französisch-sprachigem Rechner ausgeführt.
Einsteiger sollten also unbedingt zunächst das typisierte Dataset kennenlernen, und wie man darauf eine erweiterungsfähige Anwendung aufbaut. Erst danach ist die Synchronisation von Datenbank und typisiertem Dataset ein Thema.
Aber auch ein typDataset-Profi wird ohne Datenbank entwickeln: Denn die Datenbank kann er ja jederzeit hinterlegen - vorzugsweise ganz zuletzt - wenn die Anwendung bereits stabil und feature-complete läuft.
Drei Probleme würde auch ein Profi, der alles richtig zu machen weiß, unnötigerweise die ganze Entwicklungszeit mit durchschleppen, wenn er verfrüht eine Datenbank hinterlegte:
- Komplexität multipliziert sich. Dieses Problem betrifft Anfänger ungleich stärker, aber es trifft auch Kenner der Materie: Angenommen 10 Fail-Möglichkeiten beim typisiertem Dataset und nochmal 10 beim Db-Zugriff - so ergibt sich die Gesamt-Komplexität nicht als 20 Fail-Möglichkeiten, sondern multipliziert sich auf 100.
- Redundante Datenmodell-Konkretion: Das typisierte Dataset ist das in VB.NET-Code formulierte Datenmodell. Darauf baut die Anwendung auf.
Die Datenbank ist dasselbe Datenmodell, aber formuliert in SQL. Während einer Entwicklung bleibt niemals aus, dass das Datenmodell abzuändern ist, und das ist ungleich komplizerter, denn statt nur das Dataset zu ändern muss es gelöscht werden, die Datenbank geändert, und der Dataset-Assistent das typisierte Dataset komplett neu generieren - der einzige Weg, Abweichungen der beiden Modell-Konkretionen auszuschließen (vorrausgesetzt, der Assistent arbeitet ühaupt korrekt). - fehlende Portabilität: Eine Solution ohne Datenbank-Zugriff kann man zB. komplett verzippen und verschicken, und ist sofort lauffähig beim Empfänger.
Mit Datenbank geht das nicht - die müsste erst beim Empfänger installiert werden (und enthält dann keine TestDaten), Connectionstring angepasst, Versions-Probleme und und und...
Auch ein Backup zu erstellen ist ungleich komplizerter - etwa für MySql wüsste ich überhaupt nicht, wie solch bewerkstelligen. Backups sind aber generell unverzichtbar, denn auch kleine Änderungen am Datenmodell bergen das Risiko, im nicht kompilierbaren Zwischenzustand steckenzubleiben.
In hiesigen Tut gehts ja v.a. um Laden, Speichern und Verarbeiten in typisierter Manier.
Hingegen in die vier Views-Videos wird in 11 Youtube-Filmen Designer-Arbeit gezeigt, also im Dataset-Designer Datenmodell aufsetzen, und dann verschiedenste databinding-gestützte Präsentationsmöglichkeiten entwickeln, unter Verwendung von Form-Designer und Datenfenster.
Auch auf die Code-Seite wird eingegangen, denn wenn man nicht weiß, wie einfach es ist, macht man es sich unnötig schwer, oder Klartext: man macht es falsch.
Hier das aller-primitivste, wie man Daten laden und speichern kann (persistieren), ohne je irgendwo eine Typ-Konvertierungen durchführen zu müssen.
Daten
gegeben sind "komplexe" Datensätze - also jeder Datensatz enthält Text, Zahl und DateTime.
Das Bild zeigt ein kleines typisiertes Dataset (Menü-Projekt-Hinzufügen-Dataset). Zu beachten vlt. die Einstellung AllowDBNull.False und der DefaultValue. So vermeidet man Fehler, die auftreten könnten, wenn ein Wert ühaupt nicht gesetzt wurde.
Hingegen in anneren Szenarien (etwa in einem Addressbuch) mag es grade gewünscht sein, für einige Spalten auch ungesetzte Werte zulassen zu können.
Persistier-Code
Man kann die komplette Bearbeitung im DatagridView anbieten, sodaß nur Code zum Laden und Speichern zu schreiben wäre (jeweils Zwei-zeiler):
VB.NET-Quellcode
- Imports System.IO
- Imports PersistData.DataSet1
- Public Class frmPersistData
- Private _Datafile As New FileInfo("Dataset1.xml")
- Private Sub MenuStrip1_MenuClicked(ByVal Sender As Object, ByVal e As EventArgs) _
- Handles SaveToolStripMenuItem.Click, ReloadToolStripMenuItem.Click
- Select Case True
- Case Sender Is SaveToolStripMenuItem
- Save()
- Case Sender Is ReloadToolStripMenuItem
- Reload()
- End Select
- End Sub
- Private Sub Reload()
- DataSet1.Clear()
- If _Datafile.Exists Then DataSet1.ReadXml(_Datafile.FullName)
- End Sub
- Private Sub Save()
- Me.Validate()
- DataSet1.WriteXml(_Datafile.FullName)
- End Sub
- End Class
Dataset1.ReadXml()
und Dataset1.WriteXml()
sind der gesamte Persistier-Code.Fertig eine komplette Datenverarbeitung mit Zufügen/Löschen/Editieren/Sortieren nach Spalten - macht alles das gebundene DatagridView für uns.
codeseitige Datenverarbeitung
Leider sieht man dann immer wieder, wie die Leuts die Daten aus dem DatagridView puhlen, und herumkonvertieren und komische Sachen machen. Und das, obwohl die Daten doch perfekt aufbereitet im Dataset bereitstehen!
Daher habe ich noch eine kleine codeseitige Datenverarbeiterei drangemacht, die zeigt, wie man die Daten aus dem Dataset holt - nicht aus dem DataGridView (oder aus sonst einem Control), und dasses das typisierte Dataset eben ermöglicht, die gesamte Datenverarbeitung typsicher und ohne Konvertierungen durchzuführen:
VB.NET-Quellcode
- Private Sub CalculateTimeSpan()
- 'ein Beispiel, wie auf typisierte Daten zugreifen und verarbeiten
- Dim tb = DataSet1.DataTable1
- If tb.Rows.Count < 1 Then
- MsgBox("aus einer leeren DataTable kann keine Zeitspanne ermittelt wern")
- Return
- End If
- 'minimax - Ermittlung
- Dim min = tb.First, max = min
- For Each rw In tb
- If rw.ADateTime < min.ADateTime Then
- min = rw
- ElseIf rw.ADateTime > max.ADateTime Then
- max = rw
- End If
- Next
- Dim tspan = max.ADateTime.Subtract(min.ADateTime)
- Dim sTime = String.Format("{0} Tage, {1} Stunden, {2} Minuten, {3} Sekunden", _
- tspan.Days, tspan.Hours, tspan.Minutes, tspan.Seconds)
- MsgBox(String.Join(Environment.NewLine, {"Die maximale Zeitspanne beträgt:", _
- sTime, "und liegt zwischen", min.Text & " und " & max.Text}))
- End Sub
So siehts dann aus, wenn auf den Test-Button geklickst wird:
Zugegeben nicht sinnvoll, und sieht auch sch... aus.

Es geht ja auch nicht um die Berechnung, sondern um zu zeigen, dass Berechnungen auf den Daten auszuführen sind, und dass das eleganter und (typ-)sicherer ist, als in den Controls herumzuhühnern.
Zum Sample-Code:
Ich hab jetzt das CodeSample von diesem Post und das vom nächsten in eine Solution gestopft
Und nun tu ich auch noch die Solution mit den ganz vielen Samples hierher, obwohl ich darauf erst im vorletzten Post eingehe: Vb10Projects
Dieser Beitrag wurde bereits 24 mal editiert, zuletzt von „ErfinderDesRades“ ()