Ein paar generelle Fragen zum Programmieren in .NET

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von hans im glück.

    Ein paar generelle Fragen zum Programmieren in .NET

    Hallo zusammen,

    ich bin neu hier und habe bis jetzt einiges in Excel per VBA gemacht. Jetzt möchte ich weiterkommen und meinen Horizont erweitern.
    In meiner Firma haben wir eine Art Prüffragenkatalog der in Excel erstellt ist und per VBA eine Bestandskontrolle von Waren durchführt selbstständig Emails an bestimmte Verteiler verschickt usw. Prüffragen müssen markiert werden so das am Ende ggf. Punkte abgezogen werden.

    Da Excel eher der Rechenknecht ist und wir da eigentlich "nur" eine Datenverarbeitung vornehmen und das bisher Programmierte teilweise schon fast zehn Jahre alt ist würde ich das Ganze gern in VB.Net als eigenständiges Programm erstellen.

    Jetzt habe ich dinge generelle Frage. In Excel kann ich Felder befüllen, diese abspeichern, wieder aufrufen per Sverweiss auf andere Excel-Mappen zugfreien usw.
    Wie aber löst ich das in VB? Wo speichere ich Dinge ab. In Textdateien? Oder wieder in Excel-Mappen? Oder lokal in einer Datenbank? Mein Traum ist es jede gemachte Prüfung in eine Datenback zu schießen. Ich hoffe ihr versteht um was es mir gerade geht?

    Vielen Dank für konstruktive Impulse.

    Gruß, Mac

    Verschoben. ~Thunderbolt

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

    Zum Speichern der Daten gibt es natürlich viele Möglichkeiten, die Frage ist natürlich immer in wieweit diese sinnvoll sind

    -> Textdatei
    Spoiler anzeigen

    Ist einfach zu erlernen und kann schnell angewendet werden, die Nachteile sind jedoch klar auf der Hand es fehlt an Strukturierung. Auch wenn von mehren Clients darauf zugegriffen werden soll, kann schnell zu massiven Problemen kommen.


    -> XML
    Spoiler anzeigen

    Ist ebenfalls einfach zu erlernen und kann auch schnell angewendet werden, bietet im Gegensatz zu einer einfachen Textdatei aber noch die Möglichkeit Daten strukturiert darzustellen und zu speichern(Ebenfalls können Attribute hinzugefügt werden). Jedoch kann es auch hier zu Problemen kommen wenn von mehreren Clients darauf zugegriffen werden soll


    -> Access
    Spoiler anzeigen

    Schon mehr in Richtung "gute" Lösung, da die Daten in Tabellen strukturiert gespeichert werden können, aber auch bei Access-Datenbanken kann es wenn mehrere Clients darauf zugreifen zu Problemen kommen.


    ->SQL Datenbank
    Spoiler anzeigen

    Man wird mich jetzt bestimmt lynchen aber aus meiner Sicht die beste Lösung :) . Daten können strukturiert gespeichert und abgefragt werden. Korrupte Daten können wenn es sein muss mehr oder weniger leicht entfernt oder korrigiert werden. Ebenso ist ein Zugriff von vielen Clients kein Problem. Benutzereinstellungen sind mit dieser Möglichkeit ebenfalls möglich


    So viel mal dazu es liegt natürlich immer am Entwickler zu entscheiden, welche Möglichkeit schlussendlich für sein Problem die beste ist. So können auch XML-Dateien sinnvoll eingesetzt werden :D (Dafür wurden sie ja erschaffen)

    Daten in eine Excel-Datei zu speichern habe ich hier gezielt nicht aufgegriffen, da diese Methode noch umstrittener als Access-Datenbanken sein dürfte :D

    Da dein Traum aber ja schon in Richtung Datenbanken geht kann ich nur empfehlen MySQL-Datenbanken etwas genauer anzuschauen => mysql.de/ <=

    Hoffe das bringt dich schon mal weiter ...
    @Macfly123 Deine Aufgabe ist es als erstes, bevor du überhaupt etwas anfängst, die Datenstruktur der bestehenden Excel-Tabellen zu erfassen. Dafür erzeugst du dir ein Projekt, klatschst ein DataSet rein und baust dort die Tabellen zusammen, die die Datenstrukturen wiedergeben. Danach schaust du dir an, was wann und zu welchem Zeitpunkt gemacht wird. Du wirst einige Zeit keine einzige Zeile Code schreiben sondern nur analysieren, nachbauen und dokumentieren. Mach dich darauf gefasst.

    Wenn dann irgendwann mal alles in einem typisierten Dataset zusammengefügt ist, und auch der Quellcode exakt das Tut, was der VBA Teil der Excel-Mapen tut, DANN kannst du noch ne Datenbank hinter das DataSet legen. Das sind nur ein Paar Zeilen Code.

    Falls du mehr wissen willst, zum Thema DataSet und Co., such nach den Tutorials und Erklärungen von @ErfinderDesRades Die sind überall durchs Board verstreut un können praktisch nicht übersehen werden ;)

    EaranMaleasi schrieb:

    Die sind überall durchs Board verstreut
    naja, im Datenbank-Tutorial-Bereich treten sie schon bisserl gehäufter auf.

    Weiters traktiere ich jeden Anfänger mit 2 wichtigen Links:
    1) Visual Studio - Empfohlene Einstellungen - das ist das aller - aller - notwendigste, am besten, bevor man ühaupt eine Zeile Code hinschreibt.
    Und für Ex-VBA-ler gilt das umso mehr, denn vb.net ist nicht vba, aber als Ex-vba-ler ist man noch viel stärker der Versuchung ausgesetzt, diesen Unterschied zu ignorieren.
    2) Datenverarbeitungs-Vorraussetzungen
    Das ist quasi das ganze Programm. Letztendlich ists genauso notwendig wie 1), weil ohne ein Datenmodell programmieren zu können, kann man halt keine Datenverarbeitung programmieren - Jedenfalls keine, über die man nicht die Hände überm Kopf zusammenschlüge.

    EaranMaleasi schrieb:



    Wenn dann irgendwann mal alles in einem typisierten Dataset zusammengefügt ist, und auch der Quellcode exakt das Tut, was der VBA Teil der Excel-Mapen tut, DANN kannst du noch ne Datenbank hinter das DataSet legen. Das sind nur ein Paar Zeilen Code.




    also grundsätzlich habe ich es auch so gemacht und bilde mich hier und durch herrn löffelmann bereits seit 3 jahren erfolgreich weiter,
    das mit den paar zeilen stimmt imho aber nur wenn du die db extensions von edr nimmst.

    ansonsten war es mir noch nicht vergönnt ein dataset mit ein paar relationen mal so eben in zb eine access db zu schaufeln.
    ich wäre aber sehr erfreut wenn ich hier weiter kommen könnte :)
    Gruß Hannes

    VB1963 schrieb:

    Welche Art von Dataset verwendest du? Abeitest du mit typisierten DS...

    ich nehme an du meinst mich ;)
    ja habe nur typ ds, habe nach den vier views und den vielen ratschlägen hier im board gearbeitet.

    mein problem bestand darin, die tabellen in einer access db in der korrekten reihenfolge ab zu fahren. das habe ich bis heute nicht zufriedenstellend zu ende gebracht. musst aber auch verstehen ,dass ich nicht die db extension von edr nutze, da ich gerne verstehen möchte was im hintergrund passiert.

    edit: nachtrag: ein hab ich vergessen zu erwähnen, ich habe den db generator von edr benutzt um die access schmerzfrei zu erstellen (nach fertigstellung des datasets)...
    Gruß Hannes

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hans im glück“ ()

    hans im glück schrieb:

    die tabellen in einer access db in der korrekten reihenfolge ab zu fahren. das habe ich bis heute nicht zufriedenstellend zu ende gebracht
    Da sind ja die DB-Extensions gerade im Vorteil...

    MSDN schrieb:

    Um zu verhindern, dass Integritätsfehler ausgelöst werden, wird bei der Aktualisierung der Datenbank die folgende Reihenfolge empfohlen:
    [1] Untergeordnete Tabelle: Datensätze löschen.
    [2] Übergeordnete Tabelle: Datensätze einfügen, aktualisieren und löschen.
    [3] Untergeordnete Tabelle: Datensätze einfügen und aktualisieren.


    msdn.microsoft.com/de-de/libra…cs-lang=vb#code-snippet-1

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VB1963“ ()

    hans im glück schrieb:

    die tabellen in einer access db in der korrekten reihenfolge ab zu fahren.
    also hier die Speicher-Methode der DbExtensions:

    VB.NET-Quellcode

    1. Protected Overrides Sub _Save(ByVal attaches As List(Of DataTableAttach))
    2. Dim tas = attaches.Select(Function(att) Adapters(att.Table)).ToArray
    3. Dim dt = Date.Now
    4. Dim con = DataSet.Connection
    5. Using x = con.EnterOpen, tr = con.BeginTransaction()
    6. tas.ForEach(Sub(ta) ta.PrepareChangedRows())
    7. Dim suspendeds = SuspendInserterBindingSources(attaches)
    8. For Each ta In tas
    9. ta.AllCommands.Skip(1).ForEach(Sub(cmd) cmd.Transaction = tr)
    10. ta.UpdateByRowstate(DataRowState.Added Or DataRowState.Modified)
    11. Next
    12. suspendeds.ForEach(Sub(att) att.SuspendLogic(False, DataTableAttach.Suspend.BindingSources))
    13. Dim cascadeAcceptRules = New _AcceptruleCascader(DataSet)
    14. tas.ForEach(Sub(ta) ta.UpdateByRowstate(DataRowState.Deleted)) 'verbleibende Deletes mit AcceptRule.Cascade
    15. cascadeAcceptRules.Restore()
    16. tr.Commit()
    17. End Using
    18. Dbg("Update-Duration:", (Date.Now - dt).TotalMilliseconds, "ms")
    19. End Sub
    Ist Haufen Brimborium dabei, aber das Prinzip kann hoffentlich erkennbar gemacht wern:
    Zunächstmal müssen die Tabellen von vornherein in eine widerspruchsfreie Reihenfolge gebracht sein, also eine per Relation untergeordnete Tabelle darf keinesfalls vor ihrer ParentTable eingeordnet sein. Das ist an anderer Stelle mit einem listigen Sortiervorgang (topologische Sortierung) gelöst, aber wenn du deine SpeicherFunktion selbst schreibst, kannst du auch durch Kopfdenken eine gangbare Reihenfolge finden (sind meist mehrere möglich), und deine Tabellen entsprechend geordnet übergeben.
    Jo, denn gugge code:
    1. zuerst in einer Schleife (#8-#11) werden alle addeten und modifiedeten Rows geupdatet(#10), und zwar nudelt die Schleife alle Tabellen durch (in wie gesagt richtiger Reihenfolge).
    2. Dann werden die AcceptRules aller Relationen auf Cascade umgestellt (#13). Dafür habich eine Extra kleine Klasse gebaut - siehe unten.
    3. DAnn werden alle Tabellen nochmal durchgenudelt, in gleicher Reihenfolge, und die verbleibenden Deletes werden auch geupdated - #14 - ist ja auch drankommentiert.
    4. Dann die AcceptRules wieder zurückstellen #15.

    Also das Prinzip ist allgemeingültig, und man kann sone Routine auch selber coden. Wie gesagt - bei mir ist da viel Brimborium dran, das mit der Transaction, das mitte DataTableAttaches, wo DataAdapter drinne sind, und registrierete BindingSources, die während des Addens auch suspendiert werden (#7, #12), und so Sachen.
    Aber anfangen kannste ja mit diesen beiden Schleifen.
    Du müsstest deiner Methode halt die DataTables übergeben, und zu jeder DataTable auch den zugehörigen DataAdapter.
    Jo, das mitte AcceptRules, da kann man auch dran hirnen - oder du gibst als 3. Element halt auch die betroffenen Relationen an, die temporär auf Accept.Cascade zu setzen sind.
    Naja, oder halt generisch ist wohl doch am einfachsten, kannste ja das Dingens von mir für übernehmen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' setzt bei allen Relationen des Datasets, die eine ChildKeyConstraint haben, temporär die AcceptRejectRule auf .Cascade. Dieses bewirkt, dass durch Löschweitergabe verursachte Löschungen untergeordneter Rows **nicht** an die Db gesendet werden - denn die Db hat ja ihre eigene Löschweitergabe.
    3. ''' </summary>
    4. Private Class _AcceptruleCascader : Inherits List(Of Tuple(Of ForeignKeyConstraint, AcceptRejectRule))
    5. Public Sub New(ByVal dts As DataSet)
    6. For Each rl As DataRelation In dts.Relations
    7. Dim ck = rl.ChildKeyConstraint
    8. If ck.Null Then Continue For
    9. MyBase.Add(Tuple.Create(ck, ck.AcceptRejectRule))
    10. ck.AcceptRejectRule = AcceptRejectRule.Cascade
    11. Next
    12. End Sub
    13. Public Sub Restore()
    14. For Each tpl In Me
    15. tpl.Item1.AcceptRejectRule = tpl.Item2
    16. Next
    17. End Sub
    18. End Class


    @VB1963: Den MSDN-Algo findich nicht optimal, der nutzt nicht aus, dass eine DB selbst Löschweitergabe eingebaut haben kann (sollte). Dadurch entsteht unnötiger Traffic.

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

    Hallo zusammen,

    ich merke gerade ich steh völlig am Anfang, bin etwas demotiviert und blöde drein schauend. Ich will alles geil machen, in einem eigenständigen Programm und merke, dass das alles andere als leicht sein wird. Aber ich will was hinterlassen, was geiles abliefern wo alle sagen "Hammer der Typ" 8o Vielleicht weiß jemand was ich meine. Ich weiß was ich will, wie escaussehen soll usw. aber mein nicht vorhandenes Wissen über Visual Studio und SQL steht mir im Wege. Ich frage mich gerade auch wie zum Beispiel ein Inventurrtool aussehen könnte? In Excel wurde der Warenbestand importiert. Dann wird über eine Zelle ein Barcode eingescannt. Der wird mit den vorhannden Barcodes verglichen und bei Übereinstimmung die Ist-Wert hochgezählt. Wenn der Ist-Wert ond der Soll-Wert gleich sind wird die Zeile mit dem Artikel grün markiert. Ich weiß nicht mal wie ich das in WindowsForm ausgeben könnte wenn ihr versteht was ich meine.

    Sind Datasets so eine Art Container für Daten aus der Datenbank? So eine Art Zwischenspeicher um nicht immer wieder die Datenbank zu connecten?

    Ich habe einen Videolehrgang von video2brain durchgearbeitet. Alles sehr gut erklärt. Z.B. Schleifen, Variablen, Operatoren, also auch schon einiges was ich kannte. Aber nichts von Datasets, oder das arbeiten mit SQL Datenbanken usw.
    Daher die Frage wie würdet ihr an meiner Stelle vor gehen um das alles möglichst schnell auf die Schippe zubekommen? Welche Bücher kennt ihr und würdet ihr Empfehlen? Ich arbeite mit Visual Studio 13 - Express. Was sollte ich als erstes lernen? Ich kenne bereits Schleifen, Variablen, Datentypen, If-Anweisungn, Case Select usw.

    Ich hatte vor kurzem eine VBA-Schulung. Hier hätte ich mal lieber VB nehmen sollen. Aber da war das alles noch nicht so klar. Nich klar, dass ich diese Sachen übernehmen soll. In Excel kein Problem aber ich will ja weg davon.
    Ich brauch glaube ich so einige Impulse und Gedankenstützen und bedanke mich schon im vorraus herzlichst bei euch.

    Viele Grüße, Mac
    zumindest ein Trost: Schulungen taugen meist nix. ob Excel weiß nicht, aber die .Net-Sprachen... hatte gelegentlich entsprechende kleine Einblicke.

    Macfly123 schrieb:

    Sind Datasets so eine Art Container für Daten aus der Datenbank? So eine Art Zwischenspeicher um nicht immer wieder die Datenbank zu connecten?
    Das ist eine ausgezeichnete Beschreibung einer der Haupt-Eigenschaften von Datasets. :thumbsup:
    Aber es ist nur eine Haupteigenaschaften, das typisierte Dataset (wichtige Unterscheidung!!) hat noch 2 weitere Haupt-Eigenaschaften: a) Typisierung b) Databinding-Unterstützung
    Das schnellste, ums auf Schippe zu kriegen nannte ich bereits in post#4.
    Wie stehts damit - hast du die Deppen-Einstellungen inzwischen behoben?
    Und dann fang mit dem anderen Link an.

    Und fixier dich nicht zu sehr auf wie du dir das vorstellst. Eine Datenverarbeitung entwickelt man vom Datenmodell ausgehend, und die ersten Versionen sehen zT. grauenhaft aus, aber wenn sie ihren Job machen, ist man eiglich schon übern Berg.
    Irgendwelche Artikel iwan grün markieren ist hübsches Gimmik. Wird auch unterstützt, aber wenn die Struktur nicht hinhaut, kommst du garnet so weit (bzw wirst später doch alles wieder in Tonne treten müssen).
    Lies die verlinkten Artikel gründlich, und merk dir insbesondere, dass du mit Sql und Datenbanken überhaupt nichts zu tun hast - jedenfalls nicht, wenn du zügig vorankommen willst.
    Viele können das nicht fassen, wird mir auch fleissig drin widersprochen - also lies die verlinkten Artikel, lies meine Argumentation (hier: unter Vorbemerkung), dann kannst du dich ja immer noch mit Datenbanken verzetteln.
    @Macfly123 so gehts mir heute nach nun mehr als 3 Jahren noch :)
    les das löffelmann buch und frag hier, dann kommst du auch weiter. wenn du die oben genannten grundlagen hast kannste dir was die daten angeht die vier views videos anschauen, das thema datenbank kommt dann mal ganz zum schluss wenn die gesamte anwendung bereits mit typ ds und einer xml als speicherdatei funktioniert.
    @ErfinderDesRades
    ich möchte gerne nochmal auf deinen code zurück kommen. du hast natürlich die absolute deluxe variante gecodet, also im prinzip egal wieviele tabellen im ds die auch noch automatisch sortiert werden usw...

    wenn ich nun aber (ausgehend von der behauptung dass das datenmodell wirklich fertig ist) alle meine tabellen genau kenne, wäre doch dann das msn prinzip egtl. auch in ordnung oder?

    ich meine diese abfolge:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub UpdateDB()
    2. Dim deletedChildRecords As NorthwindDataSet.OrdersDataTable =
    3. CType(NorthwindDataSet.Orders.GetChanges(Data.DataRowState.Deleted), NorthwindDataSet.OrdersDataTable)
    4. Dim newChildRecords As NorthwindDataSet.OrdersDataTable =
    5. CType(NorthwindDataSet.Orders.GetChanges(Data.DataRowState.Added), NorthwindDataSet.OrdersDataTable)
    6. Dim modifiedChildRecords As NorthwindDataSet.OrdersDataTable =
    7. CType(NorthwindDataSet.Orders.GetChanges(Data.DataRowState.Modified), NorthwindDataSet.OrdersDataTable)
    8. Try
    9. If deletedChildRecords IsNot Nothing Then
    10. OrdersTableAdapter.Update(deletedChildRecords)
    11. End If
    12. CustomersTableAdapter.Update(NorthwindDataSet.Customers)
    13. If newChildRecords IsNot Nothing Then
    14. OrdersTableAdapter.Update(newChildRecords)
    15. End If
    16. If modifiedChildRecords IsNot Nothing Then
    17. OrdersTableAdapter.Update(modifiedChildRecords)
    18. End If
    19. NorthwindDataSet.AcceptChanges()
    20. Catch ex As Exception
    21. MessageBox.Show("An error occurred during the update process")
    22. ' Add code to handle error here.
    23. Finally
    24. If deletedChildRecords IsNot Nothing Then
    25. deletedChildRecords.Dispose()
    26. End If
    27. If newChildRecords IsNot Nothing Then
    28. newChildRecords.Dispose()
    29. End If
    30. If modifiedChildRecords IsNot Nothing Then
    31. modifiedChildRecords.Dispose()
    32. End If
    33. End Try
    34. End Sub



    was bei mir auch noch der fall ist: in meiner anwendung habe ich gegen deinen ratschlag die löschweitergabe nicht aktiv! es wäre einfach fatal wenn ein anwender mal eben einen kunden löscht, den Dialog auch nochmals zufällig durch amokklicken bestätigt und dann alle datensätze (in meinem fall geräte) zzgl. aller messdaten pro gerät weg sind.
    daher habe ich mich entschieden dass erst child rows gezielt gelöscht werden müssen, also eine parent row darf keine child rows mehr haben.

    dann habe ich doch auch nicht oben genanntes performance problem oder?
    Gruß Hannes

    hans im glück schrieb:

    wäre doch dann das msn prinzip egtl. auch in ordnung oder?
    jo, das msdn-Prinzip ist auch bischen einfacher umzusetzen - man muss halt nix an den Relationen rumschrauben.
    Aber nachwievor musste die Tabellen in die richtige Reihenfolge bringen, und musst den Tabellen natürlich auch den richtigen TableAdapter zuordnen.

    Und in der msdn-Variante musste die Deletes isolieren, und "bottom-up" updaten. D.h. die (topologisch geordnete) List(Of DataTable), die du brauchst, rückwärts durchlaufen.
    Den Rest dann vorwärts durchlaufen und updaten. Dabei brauchst du nicht zw. Added und Modified unterscheiden - tatsächlich kannst du sogar die ganzen Tabellen reinschmeissen.
    Weil die Deleteds die setzen nachem Update ja automatisch ihren RowState auf Accepted, die werden also in der 2. Update-Runde garnet erfasst.

    Sehr lästig wirkt sich jetzt die Typisierung der typisierten TableAdapter aus, weil die kann man garnet in eine gemeinsame Liste packen - da muss ich nochmal gucken, ob man da was drehen kann.
    Also typisiertes Dataset ist absolutes Muss, aber die typisierten TableAdapter sind eine Krankheit.
    Aber gibts da nicht auch diesen abstrusen TableAdapterManager? Der hat doch auch eine UpdateAll-Methode - funktioniert die nicht?

    ErfinderDesRades schrieb:


    Aber gibts da nicht auch diesen abstrusen TableAdapterManager? Der hat doch auch eine UpdateAll-Methode - funktioniert die nicht?


    naja die bekomme ich ja nur dann wenn ich eine fertige db importiere generiert.
    ich habe ja ein dataset erstellt, würde zur laufzeit mit deinem db generator erzeugten sql code nutzen um die access db zu erzeugen und dann die tableadapter zur laufzeit pro tabelle anlegen.

    so hab ich meine ersten tests ausgeführt.

    oder habe ich da was falsch verstanden?
    Gruß Hannes
    Das heißt also, das Thema Sql & Datenbanken sollte ich erstmal ruhen lassen und das ganze erst mal lokal bauen?
    Das mit dem Strict On wurde bereits in dem erwähnten Videotraining beschrieben und erklärt. Hab ich also eingestellt.

    Soll ich mich also erstmal mit dem speichern in XML-Dateien auseinandersetzen? Was wäre hier sinnvoll?
    Wie gesagt mach mal die vier views von edr durch (youtube Videos, glaub im Thread Datenverarbeitung einfachste Variante oder sowas in der Art, würde den Link ja einstellen bin aber mobil unterwegs). Wenn du dann deine controls auf dem form an ein typisiertes ds gebunden hast ist das speichern mit ein paar Zeilen und einem Save file Dialog erledigt.

    Wenn deine anwendung dann mit dem fertigen dataset dsfunktioniert kannste dir am Schluss Gedanken zur richtigen dB machen (siehe die Diskussion die ich grad führe)
    Gruß Hannes

    Macfly123 schrieb:

    Das heißt also, das Thema Sql & Datenbanken sollte ich erstmal ruhen lassen und das ganze erst mal lokal bauen?
    ...
    Soll ich mich also erstmal mit dem speichern in XML-Dateien auseinandersetzen? Was wäre hier sinnvoll?
    Wie in post#11 bereits gesagt: Kaum einer kann es fassen, aber es ist so.
    Wenn du mir einen Gefallen tun magst: Lies sorgfältig, was ich schreibe, und nimm es ernst.
    Dann hätten diese Fragen eigentlich nicht auftreten können. Ich habe eine Neigung, vergleichsweise schnell angepisst zu reagieren, wenn ich dasselbe nochmal erzählen muss, was ich zuvor bereits haarklein und unmissverständlich auseinandergesetzt habe.
    Da ist mir Widerspruch lieber, weil wer mir widerspricht, nimmt wenigstens ernst, was ich sage.
    Hingegen wer nur fragt, ob das wirklich so gemeint ist, was ich schrieb... - ja, es ist so gemeint, wie ichs geschrieben hab, sonst hätte ich es nicht geschrieben.

    Edit:
    Naja, sorry - ich bin wirklich überempfindlich. Eiglich bin ich ja froh, dass du ganz genau und richtig verstehst, was ich sage. Und ist eiglich auch logisch, dass du nochmal nachfragst, denn es ist schon recht unerhört, und nirgends anders kriegste die Behauptung serviert, dass Datenbänkerei ohne Sql und ohne Datenbank unvergleichlich viel leichter und schneller zu erlernen ist.
    Aber was kann ich dafür? Die Behauptung ist halt wahr, vielfach belegt, und sie ergibt sich auch ganz logisch aus den Möglichkeiten, die typDataset bietet.


    @HansGlück:
    Ich hab jetzt mal eine Schmalspur-Dataset-Adpapter-Variante gecodet, inklusive TopoSort:

    VB.NET-Quellcode

    1. Imports System.Data.OleDb
    2. Public Class DatasetPersistance
    3. Private _Con As OleDbConnection
    4. Private _Adapters As Dictionary(Of DataTable, OleDbDataAdapter)
    5. Private _RankedTables As List(Of DataTable)
    6. Private _dts As DataSet
    7. Private _IdentityCommand As OleDbCommand
    8. Public Sub New(connectionString As String, dts As DataSet)
    9. _dts = dts
    10. _Con = New OleDbConnection(connectionString)
    11. _IdentityCommand = New OleDbCommand("SELECT @@IDENTITY", _Con)
    12. Dim sorter = New TopologicSort(dts.Tables.Cast(Of DataTable))
    13. _RankedTables = sorter.rankedTables
    14. End Sub
    15. Private Function Adapters() As Dictionary(Of DataTable, OleDbDataAdapter)
    16. If _Adapters Is Nothing Then InitAdapters()
    17. Return _Adapters
    18. End Function
    19. Private Sub InitAdapters()
    20. _Adapters = New Dictionary(Of DataTable, OleDbDataAdapter)
    21. For Each tb In _RankedTables
    22. Dim adp = New OleDbDataAdapter("Select * from " & tb.TableName, _Con)
    23. Dim cmb = New OleDbCommandBuilder(adp)
    24. _Adapters.Add(tb, adp)
    25. If tb.PrimaryKey.Length = 1 AndAlso tb.PrimaryKey(0).AutoIncrement Then
    26. AddHandler adp.RowUpdated, AddressOf Table_RowUpdated
    27. End If
    28. Next
    29. End Sub
    30. Public Sub FillAll()
    31. _dts.Clear()
    32. Dim adps = Adapters()
    33. _Con.Open()
    34. For Each tb In _RankedTables
    35. adps(tb).Fill(tb)
    36. Next
    37. _Con.Close()
    38. End Sub
    39. Public Sub SaveAll()
    40. Dim adps = Adapters()
    41. _Con.Open()
    42. For i = _RankedTables.Count - 1 To 0 Step -1
    43. Dim tb = _RankedTables(i)
    44. Dim deletes = tb.Select("", "", DataViewRowState.Deleted)
    45. adps(tb).Update(deletes)
    46. Next
    47. For Each tb In _RankedTables
    48. adps(tb).Update(tb)
    49. Next
    50. _Con.Close()
    51. End Sub
    52. Private Sub Table_RowUpdated(sender As Object, e As System.Data.OleDb.OleDbRowUpdatedEventArgs)
    53. If e.StatementType <> StatementType.Insert Then Return
    54. 'bei Inserts ist bei Acces nochmal zusätzlich der Primkey abzufragen, den die Db vergeben hat.
    55. Dim primCol = e.Row.Table.PrimaryKey(0)
    56. Dim primVal = _IdentityCommand.ExecuteScalar
    57. e.Row(primCol) = Convert.ChangeType(primVal, primCol.DataType)
    58. End Sub
    59. Private Class TopologicSort
    60. 'Bevor ein Node aus dem Hashset in die Ergebnisliste verschoben wird,
    61. ' werden rekursiv all seine Vorgänger verschoben
    62. Public rankedTables As List(Of DataTable)
    63. Private tableSrc As HashSet(Of DataTable)
    64. Public Sub New(tables As IEnumerable(Of DataTable))
    65. tableSrc = New HashSet(Of DataTable)(tables)
    66. rankedTables = New List(Of DataTable)(tableSrc.Count)
    67. While tableSrc.Count > 0
    68. RecurseRankedTables(tableSrc.First)
    69. End While
    70. End Sub
    71. Private Sub RecurseRankedTables(tb As DataTable)
    72. If Not tableSrc.Remove(tb) Then Return 'gegen Kreisbezüge sichern
    73. For Each rl As DataRelation In tb.ParentRelations
    74. RecurseRankedTables(rl.ParentTable)
    75. Next
    76. rankedTables.Add(tb)
    77. End Sub
    78. End Class
    79. End Class
    Anzuwenden so:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private _persistance As DatasetPersistance
    3. Public Sub New()
    4. InitializeComponent()
    5. _persistance = New DatasetPersistance(My.Settings.BestellungPrim2ConnectionString, BestellungPrim2DataSet)
    6. End Sub
    7. Private Sub ReloadToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ReloadToolStripMenuItem.Click
    8. _persistance.FillAll()
    9. End Sub
    10. Private Sub SaveToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SaveToolStripMenuItem.Click
    11. _persistance.SaveAll()
    12. End Sub
    13. #Region "Obsolete"
    14. Private Sub ReloadToolStripMenuItem_Click_Obsolete(sender As Object, e As EventArgs) ' Handles ReloadToolStripMenuItem.Click
    15. BestellungPrim2DataSet.Clear()
    16. Me.KundenTableAdapter.Fill(Me.BestellungPrim2DataSet.Kunden)
    17. Me.BestellungenTableAdapter.Fill(Me.BestellungPrim2DataSet.Bestellungen)
    18. Me.KategorienTableAdapter.Fill(Me.BestellungPrim2DataSet.Kategorien)
    19. Me.ArtikelTableAdapter.Fill(Me.BestellungPrim2DataSet.Artikel)
    20. Me.BestelldetailsTableAdapter.Fill(Me.BestellungPrim2DataSet.Bestelldetails)
    21. End Sub
    22. Private Sub SaveToolStripMenuItem_Click_Obsolete(sender As Object, e As EventArgs) ' Handles SaveToolStripMenuItem.Click
    23. TableAdapterManager.UpdateAll(BestellungPrim2DataSet)
    24. End Sub
    25. #End Region 'Obsolete
    26. End Class
    Bei Fragen fragen, imo sollte dir aber alles so leidlich verständlich sein.
    Es ist die MS-Strategie - sieht man ja auch - beim Deleten läuft die Schleife rückwärts

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

    einige fragen bzw gedanken möchte ich vorab (meine tests kann ich erst am samstag starten) noch anhängen die mir gerade durch den kopf gingen:

    theoretisch habe ich doch mit diesem schema egtl. auch gleich multiuser mit access abgehakt oder?
    zumindest dann wenn ich nach der eingabe der daten nicht nur die bindingsource mit endedit sondern auch gleich die save methode deiner klasse aufrufe.

    oder bedenke ich da was nicht? über die reihenfolge macht sich dann ja die access db gedanken oder?
    du fragst ja mit @@identity ab wie der prim key heisst?
    last in wins wäre dann das ergebnis was ja in ordnung ist, das würde aber auch bedeuten dass beim form aufruf die fillall methode aufgerufen werden muss und nicht nur beim start der anwendung (kann ja durch einen anderen user schon änderungen in der db gegeben haben...).

    denkbar wäre dann ja auch eine automatische aktualisierung oder eine art reload button oder sowas.

    was meinste?
    Gruß Hannes
    Bei Multi-User ist immer die Concurrency-Problematik zu lösen.
    Anders als beim Abspeichern gibt es dafür keine allgemeingültige Lösung - das ist nichtmal denkbar. Es ist doch ein allgemeines quasi-mathematisches Gesetz (also höher noch als Naturgesetze):
    Wann immer mehrere von derselben Ausgangsbasis aus etwas tun, entstehen verschiedene Ergebnis-Versionen.
    Ist nur ein Ergebnis zulässig (was bei Datenbanken der Fall ist), entsteht zwangsläufig das Problem, sich zu entscheiden. Es gibt ein paar Standard-Strategien, und je nach Lage ist eine davon (oder auch was ganz proprietäres) anzuwenden.

    Das Problem selbst ist wie gesagt universal, das haben Entwickler einer Software im Team ebenso wie Eltern, die sich absprechen müssen, wer die Kinder vom Kindergarten abholt ;)

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