Daten laden, speichern, verarbeiten - Problem mit der Suche

  • VB.NET

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    Daten laden, speichern, verarbeiten - Problem mit der Suche

    Kontext: Daten laden, speichern, verarbeiten - einfachste Variante


    Hallo @ErfinderDesRades

    Vorab: Super Anleitung!!

    Ich erstelle gerade mit Hilfe Deiner Anleitung ein DataSet für meine Frau, die Arbeitet bei einem Optiker und möchte gerne das Karteikarten System von 1734 auf eine Datenbank umstellen.

    Da dort weder Access noch sonstwas installiert ist, kommt mir dieses Dataset gerade gelegen.

    Habe deine Anleitung auch umgesetzt und das meiste (Laden, Speichern, Editieren, Löschen, Sortieren) klappt schon wunderbar.

    Jetzt habe ich allerdings ein Problem mit der Suche.

    Ich habe im MenuStrip einen Button Suche und eine Textbox.

    der Code der Such Sub lautet so:

    VB.NET-Quellcode

    1. Private Sub Search(ByVal searchText As String)
    2. Dim tbl As DataTable = BrillenSet1.Tables(0)
    3. Dim rows As DataRow() = tbl.Select("Hersteller like '%" & searchText & "%'")
    4. dgvBrillen.DataSource = rows
    5. txtSearch.Text = ""
    6. End Sub


    Hier hab ich 2 Probleme. Vorab: Funktionieren tut der Code einwandfrei, egal was ich eingebe, er findet alle Datensätze und zeigt sie an, die den Kriterien entsprechen.

    ABER:

    1. Er sucht halt nur in der Spalte "Hersteller" (Klar, geb ich ja auch an), aber gäbe es vielleicht die Möglichkeit über Alle Spalten suchen zu lassen? Wenn ja, wie?
    2. wenn ich jetzt die Suche betätigt habe und habe die Gefilterten Datensätze, wenn ich dann auf "Neu Laden" drücke, stürzt das Programm ab und springt in folgende Zeile der Hauptklasse:

    In System.Data.RowNotInTableException ist eine Ausnahme vom Typ "System.Data.dll" aufgetreten, doch wurde diese im Benutzercode nicht verarbeitet. Zusätzliche Informationen: Diese Zeile wurde aus einer Tabelle entfernt und enthält keine Daten. BeginEdit() ermöglicht das Erstellen von neuen Daten in dieser Zeile. Falls ein Handler für diese Ausnahme vorhanden ist, kann das Programm möglicherweise weiterhin sicher ausgeführt werden.

    VB.NET-Quellcode

    1. <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
    2. Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")> _
    3. Public Property Hersteller() As String
    4. Get
    5. [color=#FF0000]Return CType(Me(Me.tableOHDataTable.HerstellerColumn), String)[/color]
    6. End Get
    7. Set(value As String)
    8. Me(Me.tableOHDataTable.HerstellerColumn) = value
    9. End Set
    10. End Property


    Ich werde das vermutlich mit Try, Catch abfangen müssen, aber wie und wo? oder gibt es eine sinnvollere Lösung?

    Dann hätte ich noch ein Designer Problem. Ich habe meinen Spalten bestimmte Formate gegeben (Zum Beispiel EK ist Währung) aber wenn ich dann einen wert eingebe, wird das Feld nicht formatiert....

    Hättest Du eventuell ein paar Tips für mich?

    Kann auch das Projekt anhängen falls Du dort was nachschauen musst.

    Danke schon einmal für Deine Antwort.

    Grüße

    Michael


    In eigenes Thema ausgelagert
    -Artentus
    "Hier könnte Ihre Werbung stehen..."

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Artentus“ ()

    Du kannst den Select, wie beim normalen SQL, weiter ausbauen.
    dotnetperls.com/datatable-select
    var result = table.Select("Hersteller like '%1%' OR ID like '%1%'");

    Kannst du vielleicht mal den relevanten Codeausschnitt für dein zweites Problem posten?
    TryCatch würde ich erstmal weglassen. TryCatch ist ein heißes Eisen

    Edit: Jo, war mir nicht mehr ganz sicher ob die bei Search eine Ausnahme mit dem Typisieren gemacht haben. Anscheinend nicht, deshalb auf EDR hören.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „LaMiy“ ()

    DataTable.Select() ist untypisierter Mist.
    Wo immer im Code Worte wie DataTable, DataRow auftaucht, ist man dabei, untypisierten Mist zu coden - etwa post#1, Listing#1, zeilen #2,3.
    Auf vier Views-Videos gibts auch Videos, die zeigen, wie elegant man in typisierter Manier programmiert.

    Ist mir auch nicht ganz recht, dass du, TE, sagst, der post#1-Code sei aus meiner Anleitung entsprossen.
    Weil das ist ungefähr das Gegenteil von dem, was ich in dem Tut propagiere, also man soll nie zur Laufzeit einem DatagridView eine neue Datasource geben. Sowas richtet man im Designer ein, und wenn man was suchen wil, bietet sich meist die BindingSource.Filter-Property an. Auch sowas ist in den Videos gezeigt.

    Achso - zum Filtern gibts natürlich auch Tut: DataExpressions: Filter und berechnete Spalten im Dataset

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo Ihr beiden,

    Danke für Eure Antworten.

    Hmm, ich war mir sicher den Code aus deiner Beispiel projekt entnommen zu haben....*amKopfKratz* vielleicht hab ich ihn auch bei Tante Google gefunden.

    Egal, ich hab da im Netz eine Funktion gefunden, die tut genau was ich will bei der Suche, halt eben nur über eine Spalte aber ohne Laufzeitfehler.

    VB.NET-Quellcode

    1. Private Function SelectRows(ByVal dt As DataTable, _
    2. ByVal filterstring As String) As DataTable
    3. ' Zeilen abfragen, die dem Filterstring entsprechen
    4. Dim rows_selected() As DataRow = dt.Select(filterstring)
    5. ' Tabelle für gefilterte Zeilen
    6. Dim dt_select As New DataTable
    7. ' Tabellenschema übertragen
    8. dt_select = dt.Clone
    9. ' Gefilterte Zeilen eintragen
    10. For Each row As DataRow In rows_selected
    11. dt_select.ImportRow(row)
    12. Next row
    13. ' Tabelle mit gefilterten Sätzen zurückgeben
    14. Return dt_select
    15. End Function


    Zuweisen tue ich dies dann in der Sub Search und aufrufen im TextCahnged Ereignis der Textbox:

    VB.NET-Quellcode

    1. Private Sub mnuMain_ItemClicked(sender As Object, e As EventArgs) _
    2. Handles mnuSave.Click, mnuReload.Click, txtSearch.TextChanged, _
    3. mnuBackup.Click, mnuAdd.Click, searchDel.Click
    4. Select Case True
    5. Case sender Is mnuSave
    6. Save()
    7. Case sender Is mnuReload
    8. Reload()
    9. Case sender Is txtSearch
    10. Search(txtSearch.Text)
    11. Case sender Is mnuBackup
    12. Backup()
    13. Case sender Is searchDel
    14. txtSearch.Text = ""
    15. Reload()
    16. End Select
    17. End Sub


    VB.NET-Quellcode

    1. Private Sub Search(ByVal searchText As String)
    2. dgvBrillen.DataSource = SelectRows(DataSet1.Tables(0), "Hersteller like '%" & searchText & "%'")
    3. End Sub


    Wie gesagt, das funktioniert ohne diesen Laufzeitfehler wenn ich auf Neu laden drücke.

    die Videos habe ich m,ir alle schon angeschaut und auch den 2. Link mit dem Filtern, aber auch dort beim Filtern kann ich ja immer nur nach einer Spalte filtern, oder?

    Ich verstehe das man im Designer schon einiges einstellen kann, aber so ganz blick ich noch nicht durch wie.

    Ich schaue mir die Videos noch einmal an und melde mich dann noch einmal falls ich noch Probleme habe.

    Danke Euch beiden...

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    aber auch dort beim Filtern kann ich ja immer nur nach einer Spalte filtern, oder?
    Was DataTable.Select() kann - Mehrspaltigkeit inklusive - das kann die BindingSource.Filter - Property ebensogut, und in nur einer Zeile, und ohne die gesetzten Bindings zu zerrupfen.
    Einfach mal die Dokumentation der Syntax lesen - die ist übrigens für BindingSource.Filter und DataTable.Select() dieselbe
    Hallo @ErfinderDesRades,

    ich glaub ich hab es jetzt so langsam begriffen.

    Das mit der BindingSource und dem Filter klappt BESTENS!!

    hier jetzt meine neuer Code für das Suchen:

    VB.NET-Quellcode

    1. Private Sub Search(ByVal searchText As String)
    2. OptHartDTBindingSource.Filter = "Hersteller like '%" & searchText & "%' or Modell like '%" & searchText & "%' or EK like '%" & _
    3. searchText & "%' or UVP like '%" & searchText & "%' or VK like '%" & searchText & "%'or Kalk.Faktor like '%" & _
    4. searchText & "%'or Lieferdatum like '%" & searchText & "%' or Bemerkung like '%" & searchText & "%'"
    5. End Sub


    Er sucht jetzt wirklich über alle Spalten... TOP.

    Allerdings erstellt sich hier künftig ein neues Problemchen... wenn eine Spalte hinzukommt (was in der Anfangsphase sicherlich öfter vorkommen wird), muss ich den Code anpassen und eine neue .exe raus geben.

    Frage ist hier, kann man den Filter irgendwie anders anpassen? oder muss ich immer mit dem OR Statement die Spalten hinzufügen? Ich kann ich erinnern das bei SQL Statements da ein Befehl für gibt, komme aber nicht mehr drauf wie der hieß....

    Noch ein 2. Problem:

    ich habe die Spalten Formatiert (im Dataset Designer) das zum Beispiel die EK, VK und UVP Spalte in Währung angezeigt wird. Wenn ich allerdings einen Betrag eingebe, wird die Zelle beim verlassen nicht formatiert. Muss ich das noch irgendwo Code-Technisch hinterlegen?

    Vielen Dank für Tips

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    EK, VK und UVP Spalte in Währung angezeigt wird. Wenn ich allerdings einen Betrag eingebe, wird die Zelle beim verlassen nicht formatiert.
    Keine Ahnung.
    Wenn ich im Designer eine DGV-Spalte als Währung formatiert konfiguriere, dann funzt das, ohne dass ich weiteres unternehmen muss.
    guggemol vier Views-Videos - gegen Ende kommen da auch Filmle, die die gewaltigen Formatierungsmöglichkeiten typisiert gebundener DGVs zumindest bisserl anreissen - ach, auch eine WährungsColumn kommt vor - Article.Price.
    Ah - ich kann mir vorstellen, dass dein Datenmodell untauglich ist. Wenn du EK im Dataset nicht richtig als Zahl anlegst (Decimal ist der Standard-Währungs-ZahlenTyp), sondern String, dann ists kein Wunder, wenn in Folge die Bugs nur so gekrabbelt kommen.



    Jo, wenn du die Spalten änderst, musst du natürlich auch den Filter ändern.
    Etwas automatisches gibts da zunächstmal nicht, denn eine Spalte für Zahlen-Angaben filtert man ja üblicherweise nicht mit zB dem Like-Operator, sondern mit <, =, >.
    Also man kann schon was frickeln, was die SpaltenNamen ausliest, und anhand dessen einen Filter-Ausdruck generiert.
    Ist aber bisserl Aufwand, und eben nicht allgemeingültig - da wirds immer Tabellen geben, wo so ein Filter-Generator einen Absturz provoziert.



    Ganz wichtig sind auch Backups, denn ein Form kann unrettbar kaputt gehen, wenn du ihm das Datenmodell unterm Hintern änderst.
    Da der Designer ja auch aufs Datenmodell zugreift, kannes (muss nicht, wenn man vorsichtig ist) dazu kommen, dass er das Form überhaupt nicht mehr anzeigen kann, und dann ist es irreparable kaputt, denn zum reparieren müsste er es ja anzeigen.
    Also nutze den VS-TeamExplorer oder mein SolutionExplorer - OpenSource zum Backup machen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hi,

    Danke für den Hinweis. War natürlich alles als String deklariert :(

    Die Spalten habe ich nun richtig im Designer hinterlegt und nun sind die Spalten nach Eingabe so, wie ich es haben möchte, allerdings klappt nun natürlich meine Suche nicht mehr über alle Spalten...

    habe den Suchstring auch so angepasst:

    VB.NET-Quellcode

    1. Private Sub Search(ByVal searchText As String)
    2. OptHartDTBindingSource.Filter = "Hersteller like '%" & searchText & "%' or Modell like '%" & searchText & "%' or EK = '%" & _
    3. CDec(searchText) & "%' or UVP = '%" & CDec(searchText) & "%' or VK = '%" & CDec(searchText) & "%'or Kalk.Faktor like '%" & _
    4. searchText & "%'or Lieferdatum = '%" & CDate(searchText) & "%' or Bemerkung like '%" & searchText & "%'"
    5. End Sub


    sobald ich aber etwas eingebe was zum Beispiel in der EK Spalte steht, stürzt das Programm ab.

    Kann ich das "einfach" lösen? wenn nicht, muss meine Frau halt damit leben das sie nicht in allen Spalten suchen kann sondern nur eben in 4 Spalten.... (Hersteller, Modell, Kalk.Faktor und Bemerkung)

    ich schaue mir jetzt gleich noch die "Filmle" an....

    Achja, noch eine Frage :)

    Ich habe noch ein automatisches Backup eingebaut, das heißt wenn die Anwendung startet wird von der aktuellen xml Datei ein Backup angelegt (falls mal jemand auf die Idee kommt die xml zu löschen)....

    Kann man irgendiwe den Zugriff auf die XML (ich hab die Endung schon umbenannt in .ohd dann ist wenigstens für den Laien nicht sofort die Möglichkeit dort rein zu schauen und unbeabsichtigt änderung daran vorzunehmen die das Programm dann abstürzen lassen) beschränken? oder verbieten? oder noch besser... kann das Programm diese xml nicht INNERHALB der .exe speichern sodass man von außen garnicht drauf kommt?

    Danke jedenfalls schon einmal für Eure Geduld und hilfreichen Tips...

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."
    Die Syntax der FilterExpressions kann auch Typumwandlungen durchführen. Insbesondere nach String ist sie recht mächtig.
    Dazu musste aber die Doku genau studieren, das werden recht unhandliche Filter-Ausdrücke.

    Aber vlt. wirklich hintanstellen, weil ist ja sehr fraglich, ob so ein Mega-General-Filter überhaupt sinnvoll ist.
    Hallo,

    Sinnvoll ist es für mich persönlich nicht, aber frag mal mein Frau :) da red ich gegen Windmühlen :)

    Für mich würde es sich auch nicht erschließen warum ich nach zum Beispiel EK 2,95€ suchen soll, das könnte man ja auch über das sortieren der Spalte regeln....

    Aber naja....

    Ich lasse es jetzt erstmal bei den 4 String Spalten.... das sollte eigentlich erstmal reichen...hoffe ich :)

    hast du noch einen Tip für meine 2. Frage mit dem absichern der xml Datei?

    Danke und Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    sobald ich aber etwas eingebe was zum Beispiel in der EK Spalte steht, stürzt das Programm ab.

    Klar, du willst gleichzeitig nach Date und Decimal casten, das geht ja nicht, entweder beide oder eins der beiden werden nicht gehen.

    Du könntest jeweils mit Date.TryParse und Decimal.TryParse versuchen zu casten, und wenn es geht, dann auch nur diese Spalten filtern. Also, wenn Cast nach Date funktioniert, dann wird es wohl kein Preis oder Hersteller sein usw.
    Innerhalb der Exe weiß ich nix, halte ich auch nix von.
    Zunächst mal kannst du die Datei ins AppData-Verzeichnis speichern, da ist sie schon sehr sicher (imo sicher genug), denn kein Schwein weiß wo das eiglich ist.
    Dann kannstese noch verschlüsseln: Verschlüsseln und Autentifizieren , das ist bisserl aufwändig.
    Zum Ende des ersten Posts gibts auch eine Quick&Dirty-Verschlüsselung - nicht sicher gegen ernstzunehmende Angreifer, aber mit minimalem Aufwand.
    Aber würde ich auch hintanstellen, bzw. weglassen - so sicher wie der Dateikarten-Kasten ist das auch ganz ohne Verschlüsselung.
    Hahahah... Karteikasten.... glaub mir, der sieht tatsächlich aus als hätte den mal einer um 1734 angelegt....

    Ähm ins Appdata Verzeichnis reicht völlig aus... (hätte ich auch selbst drauf kommen können....

    Hmmm, wobei ich dann erstmal schauen muss welches OS installiert ist, XP, Vista oder 7....

    Ich könnte aber auch hingehgehn (da ich das Programm dort eh selbst installiere) lege ich einfach einen DB Ordner im Programm Ordner an, und erstelle ne Verknüpfung aufm Desktop, dann kann ich es lassen wie es ist und die xml wird im Programmordner abgelegt....

    DA findet die von den dortigen Mitarbeiterinnen auch keiner :)

    Danke für Eure Hilfen, das kleine "Progrämmle" ist soweit Einsatzbereit und ich stelle mich dann jetzt mal auf die ersten Änderungswünsche ein :)

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."

    WhitePage schrieb:

    Du könntest jeweils mit Date.TryParse und Decimal.TryParse versuchen zu casten, und wenn es geht, dann auch nur diese Spalten filtern.


    Noch sauberer würde ich es aber finden, wenn du eine ComboBox-Auswahl vorgibst, nach was gefiltert werden soll (Spaltenüberschriften) und in der Textbox dann der Suchstring eingegeben wird. Dann brauchst du jeweils einen Filter nur über eine Spalte zu setzen. Und vorher mit TryParse sicherstellen, dass nur richtige Daten eingegeben werden können.
    Hi Ihr zwei,

    danke für den Hinweis, nachdem ich mir die Struktur von System.Enviroment angeschaut hatte bin ich genau auf dieses SpecialFolder getroffen und habs gleich umgesetzt...

    Auch den Tip von @WhitePage hatte ich im Vorfeld auch schon angedacht, eingebaut und von meiner Frau prüfen lassen.... mit dem Ergebnis "Ist mir zu umständlich".... *seufz*

    Hab aber eben die erste Rückmeldung bekommen das die Suche in den jetzigen 4 Feldern schon einmal ausreicht "...Fürs Erste!" sagt Sie ;(

    @ErfinderDesRades.... wie meinst Du das mit dem Backup? Zur Zeit speichere ich einfach in der Reload() Routine die aktuelle Datei unter gleichem Namen mit .bak im gleichen Verzeichnis, dadurch gehen zumindest die Daten nicht verloren...

    VB.NET-Quellcode

    1. Private Sub Reload()
    2. DataSet1.Clear() 'Bereinigen des DataSets
    3. If _Datafile.Exists Then
    4. DataSet1.ReadXml(_Datafile.FullName) 'Falls bereits eine Datenbankdatei vorhanden ist, wird diese geladen
    5. Backup() 'und gleich ein Backup der Datei erstellt
    6. End If
    7. 'Erstellung eines Timers zur Angabe von Informationen für den User
    8. btnTimer.Interval = 4000
    9. statText.Text = "Datenbank wurde geladen..."
    10. btnTimer.Start()
    11. txtSearch.Text = ""
    12. End Sub


    ich schaue mir aber gerne Deinen Thrad einmal an...

    Vor allem schon mal vielen Dank für Eure Hilfe, da lernt man echt mehr als im blöden Fernstudium.... (da wird zum Beispiel angeraten immer Option Strict ON zu programmieren, die Beispielcodes und Einsendeaufgaben klappen aber nur DANN, wenn ich Option Strict auf OFF stelle.... *seufz*)

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    da wird zum Beispiel angeraten immer Option Strict ON zu programmieren, die Beispielcodes und Einsendeaufgaben klappen aber nur DANN, wenn ich Option Strict auf OFF stelle....
    Dann machs dir zur Übung sie auf OPTION STRICT ON umzumodeln ;)

    MichaHo schrieb:

    Ich könnte aber auch hingehgehn (da ich das Programm dort eh selbst installiere) lege ich einfach einen DB Ordner im Programm Ordner an, und erstelle ne Verknüpfung aufm Desktop, dann kann ich es lassen wie es ist und die xml wird im Programmordner abgelegt....
    Oder du benutzt InnoSetup/NSIS/InstallShield mit dem du dann einen wunderschönen Installer hast, der das alles für dich erledigt. So hast du dann deine Dateien unter C:\Programme bzw. Programme (x86), alles was du brauchst in dem Ordner, nen Startmenü eintrag, eine deinstall-routine, und eine Verknüpfung aufm Desktop.

    Einziges Problem am Programme Ordner ist aber, dass man für neue Dateien i.d.R. Admin Rechte benötigt. Wenn also deine Datei nicht schon vorher besteht, solltest du dennoch auf den AppData Ordner umsteigen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    MichaHo schrieb:

    da lernt man echt mehr als im blöden Fernstudium.... (da wird zum Beispiel angeraten immer Option Strict ON zu programmieren, die Beispielcodes und Einsendeaufgaben klappen aber nur DANN, wenn ich Option Strict auf OFF stelle.... *seufz*)
    Jo, gelegentlich gewann ich schon den sehr starken Eindruck, dass vb.net-Fernstudienlehrgänge Zeit- und Geld-Verschwendung sind.
    Also wenns wirklich so ist, dass bereits deren Beispielcodes mit Strict On nicht kompilieren, dann ist doch wohl klar, dass der Lehrkörper dort schlicht inkompetent ist.



    Mit Backup meine ich nicht Backup deiner Daten, sondern Backup deiner gesamten Sourcen, inklusive Beispieldaten.
    Wie gesagt: eine ungeschickte Änderung an deim Datenmodell kann deine Forms unbrauchbar machen, sodass du sie neu aufbauen darfst. Muss man vlt. mal erlebt haben, um den Wert von Backups schätzen zu lernen.
    Hallo,

    also meinst Du ein Backup MEINER Dateien, nicht die auf dem Zielrechner (oder Programmdateien auf dem Zielrechner)

    Das schaue ich mir auf jeden Fall an...

    InnoSetup hab ich sogar installiert, aber ich bin noch zu "Blöd" das umzustezen... irgendiwe fehlt mir nach dem installieren meines Programms immer ne Datei.... aber da setze ich mich noch einmal dran wenn ich soweit vb.net verstanden habe, das auch mal sinnvolle Programme bei raus kommen. (wobei sich die künftigen Programme sicherlich hauptsächlich auf DataSets, Acess DB usw. beschränken werden, da ich das beruflich benötige)

    Danke Euch...

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."
    Hallo,

    ich muss doch noch einmal zu diesem Thema etwas fragen.

    Die Ablage der xml Datei klappt leider noch nicht.

    Den Pfad habe ich jetzt so angegeben:

    VB.NET-Quellcode

    1. 'Deklaration der Variablen zur Ablage der Datenbank Dateien
    2. Private _Datafile As New FileInfo(System.Environment.SpecialFolder.ApplicationData & "OptHart.ohd") 'Arbeitsdatei
    3. Private _BackupFile As New FileInfo(System.Environment.SpecialFolder.ApplicationData & "OptHart.bak") 'Sicherungsdatei


    leider legt er die Datei dort nicht ab....

    Könnt ihr mir bitte noch einmal helfen?

    Vielen Dank

    Grüße

    Michael
    "Hier könnte Ihre Werbung stehen..."