Access Datenbank bearbeiten

  • VB.NET

Es gibt 34 Antworten in diesem Thema. Der letzte Beitrag () ist von drschef.

    Access Datenbank bearbeiten

    Ich habe eine Access-DB vom Typ .mdb als Datenquelle in ein VB-2010-Projekt eingefügt und eine in Access vorbereitete Abfrage

    SQL-Abfrage

    1. Select * from MySort order by NR DESC


    in ein DataGridView fallen lassen. Die Daten werden richtig angezeigt. Nachfolgend werden Sätze ergänzt mit

    VB.NET-Quellcode

    1. MyDataSet.MySort.Rows.Add(ColsArr)


    Die Sätze erscheinen im Grid als letzte und nicht entsprechend der Select-Anweisung in der fallenden Reihenfolge der von mir vergebenen NR. Außerdem sind die Sätze bei einem Neustart des Programms verschwunden. Ich habe unter VB6 viel mit Access-Datenbanken gearbeitet. Aber inzwischen sieht alles völlig anders aus und das Buch "Datenbankprogrammierung mit VB 2010" hat mir trotz intensiver Recherchen noch nicht weiter geholfen. Das ist bei 1400 Seiten wohl auch nicht verwunderlich.

    - ist der Befehl ... Add hier überhaupt richtig?
    - wieso bringt der mit dem Grid verknüpfte Dataset nicht die vorgegebene Reihenfolge?
    - wie werden die Änderungen in der DB fixiert?
    Schau mal hier. Ist zwar ein Beispiel mit einem SQL Server aber es sollte eigentlich deine Fragen beantworten und ist einigermaßen leicht verständlich.

    support.microsoft.com/kb/301248/de
    "Wenn jemand in einem Betrieb unverzichtbar ist, dann ist dieser Betrieb falsch organisiert." - Roberto Niederer
    MSDN schickt dich da schön auf den Holzweg. Mit dem Ansatz wirst du kilometerweise Coden für simpelste basic CRUD - Funktionalität.

    Weiters hast du keine Chance, Databinding für dich arbeiten zu lassen, insbesondere bereits im Form-Designer. Folge: nochmal so viele Kilometer.

    Gesamt-Folge: Eine eiglich unwartbare Anwendung.

    guggemol "Datenbank in 10 Minuten" auf Movie-Tuts, wie man die vorhandenen Assistenten und Designer für sich ackern lassen kann.


    Zur Eingangs-Frage: Es ist unsinnig, die Daten sortiert vonne DB abzurufen. Sortieren kann man ganz bequem im Gui. Überzeuge dich im SampleCode des Tuts, indem du auf die SpaltenHeader klickst.
    Es ist auch unsinnig, Änderungen an die DB zu senden.
    Änderungen werden im Dataset vollzogen, und sind dann logischerweise sofort auch im Gui sichtbar.
    Zum persistieren bastel dir einen Speicher-Button, der alle Änderungen auf einmal in die DB schreibt. Das Dataset unterstützt dich dabei perfekt, denn es hat eine Änderungs-Verfolgung eingebaut, also es ist wirklich nicht mehr Code erforderlich, als im Tut gezeigt ( < 50 Zeilen )

    Üblicherweise werden meine Hinweise verworfen, wohl wg Radikalität. Aber du kannst dich auch selbst davon überzeugen, dass mein Ansatz der von Microsoft so konzipierte ist - gugge Forms over Data Videos

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

    Danke ErfinderdesRades.

    Dass die Sortierung nicht geht, ist nicht sehr beglückend. Und das Umsortieren mit dem GUI bedeutet einen Schritt mehr gegenüber der ungebundenen Nutzung des Grids. Da ließ sich die Sortierung machen. Beim Aufruf von "Datenbank in 10 Minuten" kann ich lesen "Die Projektmappendatei ...kann nicht konvertiert werden, da sie nicht bearbeitet werden kann ..."

    Bei dem von milaim empfohlenen Microsoft-Beispiel bewirkt die erforderliche Anpassung der Connectionstring die im Internet vielfach nachzulesende Meldung "Der Microsoft.Jet.OLEDB.4.0-Provider ist nicht auf dem lokalen Computer registriert" gegen die auf 64 Bit-Systemen kein Kraut gewachsen zu sein scheint. Wieder woanders habe ich gelesen, dass man mit der aktuellen accdb eine Access-Lizenz auf dem Zielrechner benötigt.

    Die Beispiele auf CD zu dem 1400-Seiten-Buch "Datenbank-Programmierung mit VB2010" führen beim Start in VB (wohlgemerkt 2010) zu einem halben Dutzend Fehlern. Wenn es so weiter geht, versteht bald keiner mehr niemanden.

    Die Vielzahl der Hard- und Software-Komponenten auf unterschiedlichen Entwicklungsstadien lässt immer mehr Raum für offene und heimliche Unverträglichkeit und eine rasante Inflation von Erfahrungen und Kenntnissen. Mein Problem ist wahrscheinlich, dass ich einen 64 Bit-Rechner mit Windows 8 und Access 2010 habe.
    Dass die Sortierung nicht geht, ist nicht sehr beglückend.
    Dochdoch - die geht schon (also wenn du mit "die Sortierung" iein schnucklige Sql meinst).
    Nur man braucht es nicht, weil im datengebundenen DatagridView eine Sortierung beliebiger Spalten bereits eingebaut ist (auf einen Spaltenheader klicken)

    drschef schrieb:

    "Die Projektmappendatei ...kann nicht konvertiert werden, da sie nicht bearbeitet werden kann ..."
    Das kann man im DateiBrowser ändern.
    Aus ieinem Grund werden manchmal gedownloadete Zips als ReadOnly entpackt. Rechtsklick auf den Ordner - "Eigenschaften", und Schreibschutz entfernen.

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

    Hallo ErfinderDesRades,

    die Möglichkeit der Sortierung in einem Grid kenne ich natürlich. Aber ich kenne eine Menge, die nicht wissen, das man ein Grid nach den Spalten sortieren kann oder die Spaltenbreite verändern kann. Und deshalb hatte ich den Wunsch, die Sortierung des Grids von Anfang an so zu bestimmen, dass die chronologisch letzten Sätze beim Einfügen oben dran stehen, damit man sie zuerst sieht (also fallende Sortierung). Auch das u.a. mit dem Hintergedanken, dass der unbedarfte Anwender sonst dasitzt und keine Wirkung vom Einfügen sieht. Es geht natürlich auch mit Trickserei.

    Das Beispiel habe ich inzwischen nach Empfehlung geöffnet und da kommt wieder der Kommentar "Der 'Microsoft.Jet.OLEDB.4.0'-Provider ist nicht auf dem lokalen Computer registriert". Aber ich habe mir die Quelle angeschaut und da kann ich erst mal sicher ein Stück weiter. Ich melde mich!

    Danke
    Auf der Site habich doch auch eine Code-Version für den neuen OleDB-Treiber eingestellt, weil Win7 mit dem ollen Kram nicht mehr klarkommt.
    musste nochma gugge.

    Und was man mittm Spaltenkopf sortiert, kann man auch im Designer an der BindingSource einstellen, etwa

    VB.NET-Quellcode

    1. me.CategoryBindingSource.Sort = "CategoryName"
    fertig.

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

    Vielleicht wird es doch noch!

    Hallo,

    ich danke für die Anregungen und werde ihnen nachgehen. Durch Nacht zum Licht (vielleicht). Aber leider muss ich erst mal ein wenig Abstinenz üben - eine Woche Wintersport. Danach greife ich die Anregungen auf.

    (Ich bin vielleicht ein wenig frustriert und blockiert, weil ich vor Jahren mit VB6 und Access ein Dutzend Anwendungen mit allen möglichen Besonderheiten programmiert habe. Und auf einmal steht man da wie ein dummer Junge und stolpert von einem Schlagloch ins andere.)

    Danke erst mal. Ich melde mich in 8-10 Tagen.

    drschef schrieb:

    (Ich bin vielleicht ein wenig frustriert und blockiert, weil ich vor Jahren mit VB6 und Access ein Dutzend Anwendungen mit allen möglichen Besonderheiten programmiert habe. Und auf einmal steht man da wie ein dummer Junge und stolpert von einem Schlagloch ins andere.)
    VB.Net ist zu Vb6-Umsteigern wirklich grausam.

    Die Wahrheit ist nämlich: Es gibt keinen "Umstieg".
    VB.Net ist von VB6 so weit entfernt ist wie Html von Java.

    Ohne Übertreibung: Du mußt alles vergessen, was du je gedacht hattest, zu können. Weil es gibt nichts, gar nichts, was in vb.net nicht komplett anders gemacht wird (und viel besser) als in olle vb6.

    Kompliment, übrigens! :thumbsup:
    Indem dir das selbst auffällt, hast du das vlt. schwierigste Lernhinderniss - na, "überwunden" ist übertrieben - aber doch lokalisiert.

    Du glaubst nicht, wieviele vb.net-progger noch nach jahren immer noch im grunde vb6-code produzieren.
    Und vb6-Code läuft leider noch, ist aber im VB.net-Kontext einfach grotten-schlecht.
    Wieder zurück aus dem Winterurlaub! Und Dank an ErfinderDesRades. Trostreiche Worte und Hilfe: Der Hinweis zur Sortierung mit der BindingSource hat mein Vertrauen wieder hergestellt. Dann habe ich mir das nützliche OLEDB12-Beispiel vorgenommen. Inzwischen bin ich bei der Umsetzung eines (nur mit Textdateien arbeitenden, aber inzwischen 40.000 Datensätze umfassenden) vorhandenen Projektes. Da sind viele Einzelfragen zu klären, aber jetzt bin ich wieder optimistisch.

    Ich lasse auf jeden Fall von mir hören - entweder, wenn ich wo hänge oder wenn ich endgültig über den Berg bin.

    Es lebe das Forum!!!

    Aktueller Stand und Problem

    Ich bin nach Pause wieder dran. Das ist der Stand:

    Locale Datenbank:

    Quellcode

    1. connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Gert\AppData\Roaming\Fotoverwaltung\FVDB.accdb"


    - Gefüllte Datenquelle (accdb) ins Projekt (VB2010) eingebunden (ohne Kopie, d.h. Änderung am Originalplatz)
    - 2 Tabellen (1:n-Relation) mit DragDrop einem DataGridView und einer Listbox zugeordnet
    - Fallende Sortierung im DataGridView mit Bindingsource erfolgreich
    - Funktion LoadDS erfolgreich => Anzeigen im Datragrid und in Listbox
    - Funktion ClearDS erfolgreich - FVDataSet.Clear() => Grid wird leer
    - Funktion SaveDS erfolglos => Datenbank bleibt ungeändert

    Nach dem Komplett-Löschen 'ClearDS' zeigte das Grid nichts mehr an und die resultierende Anzahl im Tableadapter ist gleich 0, also war das 'interne' Löschen erfolgreich.
    Für 'SaveDS' habe ich mich erfolglos an das Beispiel angelehnt. Aber der Count der gelöschten Zeilen war trotz der Komplettlöschung = 0.

    Quellcode

    1. Dim DelRowsFV As DataRow() = Me.FVDataSet.Fotoverzeichnis.Select("", "", DataViewRowState.Deleted)
    2. WriteProt("Gelöscht FV: " & DelRowsFV.Count)
    3. Me.FotoverzeichnisTableAdapter.Update(DelRowsFV)


    Folgende andere Notation war ebenfalls erfolglos:

    Quellcode

    1. Dim DelRowsFV As FVDataSet.FotoverzeichnisDataTable = CType(FVDataSet.Fotoverzeichnis.GetChanges(Data.DataRowState.Deleted), FVDataSet.FotoverzeichnisDataTable)


    DelRowsFV war nach dem Löschen Nothing.
    Ich verstehe nicht genau was du da machst, aber mein Update führe ich bspw. immer so durch:


    VB.NET-Quellcode

    1. Me.Validate()
    2. Bindingsource.EndEdit
    3. if Me.Dataset.HasChanges=true then
    4. Me.TableAdapterManager.UpdateAll(Me.Dataset)
    5. end if
    Gruß von der KSE

    ks-entwicklung.de

    Danke für den Tip

    Ich verstehe nicht genau was du da machst, aber mein Update führe ich bspw. immer so durch:

    Meine bisherigen Versuche erschienen mir selbst zweifelhaft und zudem noch kompliziert. Aber sie erfolgten nach vielen Recherchen und Empfehlungen. Jetzt habe ich die kompakte Form 'UpdateAll' erfolgreich ausprobiert. Aber ich bin auch auf einen neuen Konflikt gestoßen: Wenn ich mit

    Quellcode

    1. Grid.Rows.RemoveAt(Grid.Rows(i).Index)


    lösche, bildet sich das nach UpdateAll in der DB richtig ab. Ebenso funktioniert das Ergänzen von Sätzen. Doch Bei dem Versuch, mit 'DataSet.Clear' alle Daten zu löschen, verschwinden diese zwar auch aus der Darstellung im Grid und die Überprüfung der Counts zeigt, dass die Löschung erfolgt war. Doch das nachfolgende 'UpdateAll' bleibt wirkungslos. Das heißt, die Daten sind alle noch da. Wo kann diese Unverträglichkeit herrühren? Ist da irgendeine Plattform zu empfehlen, die 'UpdateAll' in einem größeren Zusammenhang erläutert, zum Beispiel ein Anwendungsbeispiel mit typischen Datenbankoperationen, ein Forumsbeitrag oder eine Beschreibung von Microsoft?

    Ein Problem sehe ich darin, dass viele Beiträge in den Foren nicht genügend klar auf die Umgebungsbedingungen eingehen, wie Betriebssystemversion, .net Framework Version, OLEDB-Version, Visual Basic-Version, Access-Version. Da macht nicht einmal MS mit seinem unendlichen Materialpool eine Ausnahme. Aber die Vielfalt und Kombinatorik wird immer größer. Und je größer, desto mehr an Randbedingungen werden bei den Beiträgen weggelassen. Damit stellen ältere Beiträge eine zunehmende Gefahr dar.

    Ausprobiert

    Versuche es bei DataSet.Clear vor dem Speichern noch mit DataSet.AcceptChanges()...
    Danke für den Tip. Hat aber leider nichts gebracht. Löschung kommt einfach nicht an. Bei dem AcceptChanges kann man übrigens nachlesen, dass damit bestimmte Flags gelöscht werden, die wichtig für die Erkennung von jedweden Änderungen sind, so dass nachfolgende Updates ins Leere greifen.

    Wie gesagt es gibt die Alternative des satzweisen Löschens. Aber wenn möglich, versucht man das Ganze ja besser zu verstehen. Und während in dem einen Fall das globale Kommando UpdateAll die Lösung bringt, scheint das globale Kommando Dataset.clear zu versagen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „drschef“ () aus folgendem Grund: Klarere Formulierung

    Finger weg von .AcceptChanges!

    drschef schrieb:

    Bei dem AcceptChanges kann man übrigens nachlesen, dass damit bestimmte Flags gelöscht werden, die wichtig für die Erkennung von jedweden Änderungen sind, so dass nachfolgende Updates ins Leere greifen.
    Genau.

    .AcceptChanges setzt die ÄnderungsVerfolgung des Datasets zurück auf .Unchanged. Daraus folgt, das bei einem anschließendem .Update nix an die DB gesendet wird, weil alle Datensätze ja "unchanged" sind.
    .AcceptChanges sollteman als interne Methode betrachten, vorbehalten den DataAdaptern, die sie intern aufrufen, nachdem ein Update oder ein Select erfolgreich durchgeführt wurde.
    Wenn also die geladenen Daten und die Datenbank-Daten tatsächlich in 100% Übereinstimmung sind.

    Das ist eben das Problem an Dataset/DataTable.Clear. Das löscht nicht nur die Daten, sondern auch die Änderungsverfolgung, und folglich denkt Update, es sei nix zu tun.
    Die Lösung ist bisserl komplex, nämlich alle DataRows aller DataTable einzeln löschen. Das kann man sehr performant umsetzen, indem man sich nur die TopLevel-DataTables vorknöpft, weil untergeordnete Datensätze werden ja automatisch durch die Löschweitergabe eliminiert.

    VB.NET-Quellcode

    1. For Each tb As DataTable In myDataset.Tables
    2. If tb.ParentRelations.Count = 0 Then
    3. For Each rw As DataRow In tb.Rows
    4. rw.Delete()
    5. Next
    6. End If
    7. Next
    Ist im Grunde aber ganz abwegig - wer will denn komplett alle Daten, die geladen sind, endgültig und aus der Datenbank löschen?

    Naja - wenn man eine bisherige Bearbeitung komplett verwirft, und die Daten frisch lädt, dann kann DataTable.Clear sinnvoll sein. Aber komplett: Dataset.Clear()?

    Edit: Ich bin wirklich verwirrt, dass du dein Projekt auf auf der OriginalDatei mit 40000 Datensätzen arbeiten lässt, und dann ein ganzes Dataset löschen willst, also evtl. die ganze DB weghauen.
    Was ich dir allerwärmstens empfehle: Backup machen!.

    Bei die Datenbänkerei kann man sich wunnebar verdaddeln, auch in anneren Bereichen als nur dem DB-Zugriff. Da kann ein eine unbedachte Änderung oder auch Designer-Bug das ganze Projekt unrettbar verwüsten.
    Nimm dir die Zeit, und bring SolutionExplorer bei dir ans Laufen, und überprüfe, dasser dein Projekt korrekt backupt.
    Dann kannst du vor jeder grundlegenden Änderung mit einem Klick ein funktionsfähiges Backup erstellen.

    Ich hätte noch radikalere Vorschläge, sowohl in Richtung leichter Einstieg: Datenbänkerei-Einstieg

    als auch in Richtung komplexes Produktiv-Framework: DBExtensions
    Beachte in letzterem auch meine vier Views - Theorie ;)

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

    .AcceptChanges hat übrigens ein Brüderchen, was sich leichter nachvollziehbar verhält: .RejectChanges().
    .AcceptChanges und .RejectChanges() implementieren glaub was inne Datenbänkerei unter "Transaktion" konzipiert ist, und dort redet man von "Commit und Rollback" - kannst die Begriffe ja auf Wiki nachlesen.
    Oder kurz: Eine Transaktion fügt viele EinzelAktionen zu einer Einheit zusammen. Failt eine Einzelaktion, so wird der gesamte Cluster rückgängig gemacht, damit keine Daten-Inkonsistenzen in die DB gelangen.
    Nu ist der AcceptChanges-Commit halt tückisch, weil er unabhängig vom wirklichen Commit (Senden der Änderungen an die DB) vollzogen werden kann.
    Könnte man nun diskutieren, ob das ühaupt ein Commit ist, weil fürs System DB-Dataset ists kein Commit, aber Dataset-intern ist das ein Commit.
    .RejectChanges (alias "Rollback") ist da gutmütiger, weil das entfernt die Änderungen aus dem Dataset, und dann ists ja korrekt, dass die Datarows den Status "UnChanged" haben, weil dann sind sie ja wieder kongruent zu den DB-Daten.

    Einfach toll!

    Danke Erfinder des Rades! Mit der Erklärung
    .AcceptChanges setzt die ÄnderungsVerfolgung des Datasets zurück auf .Unchanged.

    löst sich mein aktuelles Problem in Wohlgefallen auf. Die Erklärung ist plausibel und beseitigt den scheinbaren Widerspruch. Deine Empfehlung das Löschen als Zyklus zu programmieren hatte ich schon als Alternative eingebaut. Außerdem bildet der Vorschlag von KSE

    Quellcode

    1. Me.TableAdapterManager.UpdateAll(Me.Dataset)

    für mich die Lösung um Änderungen an die DB zu senden.

    Das Komplettlöschen ...

    Ist im Grunde aber ganz abwegig - wer will denn komplett alle Daten, die geladen sind, endgültig und aus der Datenbank löschen?
    Stimmt, aber Ich habe ein Kommando, mit welchem ich zu Beginn die DB aus einer ASCII-Datei fülle. Und da verwende ich das Komplettlöschen, um zuerst den aus einem vorhergehenden Test stammenden (evtl. falschen) Inhalt zu entfernen.

    Es macht richtig Spaß, auf so viel Interesse zu stoßen und so gute Anregungen zu bekommen.