Relativ wenig bekannt zu sein scheint die Möglichkeit, ein Dataset mit .WriteXml direkt auf Platte zu schreiben, und mit .ReadXml wieder einzulesen.
Dabei ist das Verfahren überaus simpel, schnell, und spart Festplatte. Auch ist man unabhängig von einem Datenbanksystem (DBMS). Und man spart sich den ganzen Aufwand und die Fußfallen, die ein klassischer DB-Zugriff so mit sich bringt.
Selbst wenn man ein DBMS verwenden will, kann das Verfahren während der Entwicklung überaus nützlich sein, denn man kann das Datenmodell viel leichter ändern und weiter-entwickeln, als wenn man immer zunächstmal die hinterlegte DB überarbeiten müsste.
Ein DBMS kann man immer noch später hinterlegen, wenn das Datenmodell ausgereift ist. In vielen Fällen isses aber nichtmal nötig, denn Datasets bis 20MB stellen kein Speicherproblem dar, und sind schneller komplett eingelesen, als die kleinste Abfrage über einen DBMS-Provider in Anspruch nimmt. Und 20 MB Daten muß man erstmal vollkriegen .
Ich habe schon mit 400MB-Datasets gearbeitet, und zu meiner eigenen Überraschung kein Performance-Problem feststellen können (aber 400MB scheint mir wirklich bischen irre).
Nebenbemerkung
Hier ein Thread, wo sich Vatter und SpaceyX (letzterer sogar mit Video!) die Mühe gemacht haben, bebilderte Anleitungen zu geben, wie das Geklickse zum Einrichten eines typisierten Datasets vonstatten gehen kann: Listview_Inhalt_speichern_/_auslesen
Weitere Filmles dazu: vier Views-Videos
/Nebenbemerkung
Das Projekt zeigt auch 2 (von 4) klassischen Views, die man mit Databinding zusammenkloppen kann:
1) ParentChild-View: Aus einem DatagridView kann eine Kategorie gewählt werden - ein zweites DGV zeigt die zugehörigen AddOns (ist egal, wasses ist - sind Datensätze halt)
2) Einzelblatt-View: bestimmte Werte sind zu lange Strings, als dass sie als Tabellenspalte angezeigt werden könnten. Diese werden in datengebundenen Textboxen angezeigt: Also man wählt im AddOn-DGV ein AddOn, und die Textboxen zeigen den Link zum AddOn und die Description (nur sinnlose Beispiele).
Die ganze Geschichte wird unter intensiver Verwendung der vorgesehenen Designer umgesetzt: FormDesigner, DatasetDesigner und DatenFenster der IDE.
Designer gewährleisten korrekt konfigurierte Objekte, und verstecken den eigentlich trivialen, aber sehr umfangreichen Konfigurier-Code in partialen Klassen (Endung: .Designer.vb). Das ist ein großer Vorteil, weil man sich dann im UserCode aufs Wesentliche konzentrieren kann.
Das Sample etwa ist eine voll editierbare Datenbank-Anwendung, als UserCode sind aber nur folgende paar Zeilen erforderlich, um laden und speichern zu managen, inklusive einer intelligenten "Änderungen speichern?" - Abfrage beim Schließen des Forms:
Hinweise
.
Dabei ist das Verfahren überaus simpel, schnell, und spart Festplatte. Auch ist man unabhängig von einem Datenbanksystem (DBMS). Und man spart sich den ganzen Aufwand und die Fußfallen, die ein klassischer DB-Zugriff so mit sich bringt.
Selbst wenn man ein DBMS verwenden will, kann das Verfahren während der Entwicklung überaus nützlich sein, denn man kann das Datenmodell viel leichter ändern und weiter-entwickeln, als wenn man immer zunächstmal die hinterlegte DB überarbeiten müsste.
Ein DBMS kann man immer noch später hinterlegen, wenn das Datenmodell ausgereift ist. In vielen Fällen isses aber nichtmal nötig, denn Datasets bis 20MB stellen kein Speicherproblem dar, und sind schneller komplett eingelesen, als die kleinste Abfrage über einen DBMS-Provider in Anspruch nimmt. Und 20 MB Daten muß man erstmal vollkriegen .
Ich habe schon mit 400MB-Datasets gearbeitet, und zu meiner eigenen Überraschung kein Performance-Problem feststellen können (aber 400MB scheint mir wirklich bischen irre).
Nebenbemerkung
Hier ein Thread, wo sich Vatter und SpaceyX (letzterer sogar mit Video!) die Mühe gemacht haben, bebilderte Anleitungen zu geben, wie das Geklickse zum Einrichten eines typisierten Datasets vonstatten gehen kann: Listview_Inhalt_speichern_/_auslesen
Weitere Filmles dazu: vier Views-Videos
/Nebenbemerkung
Das Projekt zeigt auch 2 (von 4) klassischen Views, die man mit Databinding zusammenkloppen kann:
1) ParentChild-View: Aus einem DatagridView kann eine Kategorie gewählt werden - ein zweites DGV zeigt die zugehörigen AddOns (ist egal, wasses ist - sind Datensätze halt)
2) Einzelblatt-View: bestimmte Werte sind zu lange Strings, als dass sie als Tabellenspalte angezeigt werden könnten. Diese werden in datengebundenen Textboxen angezeigt: Also man wählt im AddOn-DGV ein AddOn, und die Textboxen zeigen den Link zum AddOn und die Description (nur sinnlose Beispiele).
Die ganze Geschichte wird unter intensiver Verwendung der vorgesehenen Designer umgesetzt: FormDesigner, DatasetDesigner und DatenFenster der IDE.
Designer gewährleisten korrekt konfigurierte Objekte, und verstecken den eigentlich trivialen, aber sehr umfangreichen Konfigurier-Code in partialen Klassen (Endung: .Designer.vb). Das ist ein großer Vorteil, weil man sich dann im UserCode aufs Wesentliche konzentrieren kann.
Das Sample etwa ist eine voll editierbare Datenbank-Anwendung, als UserCode sind aber nur folgende paar Zeilen erforderlich, um laden und speichern zu managen, inklusive einer intelligenten "Änderungen speichern?" - Abfrage beim Schließen des Forms:
VB.NET-Quellcode
- Imports AddOnDB.DBSampleDataSet, System.IO
- Imports System.ComponentModel
- ' Parent-Child-View der Relation Category-AddOn:
- ' Im linken Grid kann man eine Kategorie anwählen, das rechte Grid zeigt daraufhin die dieser Kategorie zugehörigen AddOns an. Beide Tabellen sind vollständig editierbar.
- 'Der AddOn-View ist zusätzlich mit einem EinzelblattView ausgestattet: Da die Werte "Link" und "Description" nicht in eine Tabellenspalte passen, werden sie in datengebundenen Richtextboxen angezeigt.
- Public Class frmParentChild
- Private _DataFile As New FileInfo("..\..\DBSample.DataSet.xml")
- Private Sub frmParentChild_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
- Reload()
- End Sub
- Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
- Handles ReloadToolStripMenuItem.Click, SaveToolStripMenuItem.Click, TestToolStripMenuItem.Click
- Select Case True
- Case sender Is ReloadToolStripMenuItem
- Reload()
- Case sender Is SaveToolStripMenuItem
- Save()
- Case sender Is TestToolStripMenuItem
- Dim addOn = DirectCast(DirectCast(AddOnSource.Current, DataRowView).Row, AddOnRow)
- With New StringList
- .AddLine("hier könnte mit folgendem Datensatz was passieren:")
- .AddLine("Name: ", addOn.Name)
- .AddLine("Version: ", addOn.Version)
- .AddLine("Description: ", addOn.Description)
- .AddLine("Link: ", addOn.Link)
- MsgBox(.ToString)
- End With
- End Select
- End Sub
- Private Sub frmParentChild_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) _
- Handles Me.FormClosing
- If e.Cancel Then Return
- Dim frm = DirectCast(sender, Form)
- If Not DBSampleDataSet.HasChanges Then Return
- Select Case MessageBox.Show( _
- frm, "Änderungen speichern?", "Das Ende ist nahe", MessageBoxButtons.YesNoCancel)
- Case Windows.Forms.DialogResult.Yes
- Save()
- Case Windows.Forms.DialogResult.No
- 'nix tun
- Case Windows.Forms.DialogResult.Cancel
- e.Cancel = True
- Return
- End Select
- e.Cancel = False
- End Sub
- Private Sub Save()
- 'Validate überprüft alle aktuellen Control-Eingaben, und **übernimmt sie in die Datasource**. Letzteres ist wichtig, da ansonsten der User überrascht wird, weil seine letzte Eingabe gecancelt würde.
- 'AcceptChanges markiert alle Datensätze als übereinstimmend mit der "Datenbank" - wichtig für den Dataset.HasChanges-Test im FormClosing
- Me.Validate()
- Me.DBSampleDataSet.WriteXml(_DataFile.FullName)
- DBSampleDataSet.AcceptChanges()
- Media.SystemSounds.Asterisk.Play()
- End Sub
- Private Sub Reload()
- Me.DBSampleDataSet.Clear()
- If _DataFile.Exists() Then
- Me.DBSampleDataSet.ReadXml(_DataFile.FullName)
- Else
- MsgBox(String.Concat( _
- "Leider (noch) kein DatenFile vorhanden", Lf, _
- "Sie können aber trotzdem fortfahren, und eines anlegen."))
- End If
- DBSampleDataSet.AcceptChanges()
- End Sub
- End Class
Hinweise
- Die #Region "allgemein verwendbare Funktionalität" im SampleCode von Phonebook stellt eine verbesserte Variante für Laden, Speichern und Schließen-Abfrage dar, welche schneller lädt, und einige unerfreuliche Bugs umgeht, die in anspruchsvolleren Binding-Szenarien auftreten können (nicht müssen).
- Tutorial: Daten Filtern und berechnete Spalten im Dataset - geht auf einen hier nicht behandelten Aspekt der "Dataset-Power" ein
.
Dieser Beitrag wurde bereits 13 mal editiert, zuletzt von „ErfinderDesRades“ ()