Sehr viele Werte in DB-Tabelle speichern

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Gerrit.

    Sehr viele Werte in DB-Tabelle speichern

    Guten Morgen liebes Forum

    Ich habe in einer Form bis jetzt mehr als 17 Werte die ich in eine Tabelle (tbl_messung) speichern möchte.
    Beispiel:

    ph-Wert, Leitwert, Temperatur, Bearbeiter, reinigung, datum, uhrzeit aus Tank1 und Tank2 und Tank3

    Also im prinzip 3 mal die gleichen Werte für 3 verschiedene Tanks.

    Ich würde das jetzt so realisieren: (als Beispiel)

    VB.NET-Quellcode

    1. Imports MySql.Data.MySqlClient
    2. Module WriteMeasurement
    3. Public Function SchreibeMessung(myDate, myTime, myLeitwertTank1, myphWertTank1, myTemperaturTank1, myFilterTank1, myReinigungTank1, myLeitwertTank2, myphWertTank2, myTemperaturTank2, myFilterTank2, myReinigungTank2, myLeitwertTank3, myphWertTank3, myTemperaturTank3, myFilterTank3, myReinigungTank3)
    4. 'mysql kommando definieren
    5. Dim myQuerySchreibeMessung As New MySqlCommand(MySqlInsertMessung(myDate, myTime, myLeitwertTank1, myphWertTank1, myTemperaturTank1, myFilterTank1, myReinigungTank1, myLeitwertTank2, myphWertTank2, myTemperaturTank2, myFilterTank2, myReinigungTank2, myLeitwertTank3, myphWertTank3, myTemperaturTank3, myFilterTank3, myReinigungTank3), con)
    6. Dim myResultSchreibeMessung As Object
    7. Dim schreibeMessungError As Boolean = False
    8. 'mysql kommando ausführen
    9. myResultSchreibeMessung = myQuerySchreibeMessung.ExecuteScalar()
    10. 'wenn abfrage ohne ergebnis fehler melden
    11. If IsDBNull(myResultSchreibeMessung) Then
    12. 'wenn abfrage ohne ergebnis
    13. schreibeMessungError = True
    14. End If
    15. Return schreibeMessungError
    16. End Function
    17. End Module


    Meine Frage:

    Wäre das so eine gute Lösung mit der langen "Wurst" an Einträgen?
    Und wenn hier noch mehrere Einträge dazu kämen, wird das nicht zu lange? Also die "Public Function SchreibeMessung" wäre ja ziemlich lange.

    Grüße und Danke

    Gebhard

    CodeTags korrigiert ~VaporiZed

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

    ich empfehle, mit typisiertem Dataset zu arbeiten, sowie mit DataAdaptern.
    Ein DataAdapter enthält ein vorkonfiguriertes Set der CRUD-Commands, also Select Update Insert Delete.
    DataAdapter kann man so programmieren, dass sie sich automatisch selbst konfigurieren, sodass sie zu Datenbank und Dataset passen.
    Weiters kann man einen "Dataset-Adapter" programmieren, der sämtliche Datenzugriffe, also Select Update Insert Delete, für alle Tabellen auf jeweils einen Einzeiler reduziert.

    Ohne so eine Infrastruktur
    • programmiert man sich dumm und dämlich
    • fehleranfällig
    • ungeschützt gegen SqlInjection-Angriffe.
    Aber ist 'ne Menge zu lernen, zunächstmal wie man ein typDataset nutzen kann - such mal im Datenbank-Tutorial-Bereich nach "vier Views" - da habich einige Video-Tuts eingestellt.
    Bevor Du weitermachst, bitte die empfohlenen VS-Einstellungen verwenden. Allein Zeile#5 ist ja ne Datentypkatastrophe.
    Mir scheint, dass in so vielen Parametern mehrere Objekte drinstecken, die auch gern als solche behandelt und übergeben werden wollen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo

    und Danke für eure Antworten und hinweise.

    Um es kurz zu machen für einen Eintrag in eine DB wie im Bild unten gibt es einfachere Methoden wie von euch beschrieben.

    Um nicht unverschämt zu sein gibt es beispiele im Netz die so etwas schon einmal behandelt haben?

    Ich möchte so viel wie möglich selber machen/lernen bin aber sehr dankbar über die Hilfe aus diesem Forum.

    Grüß Gebhard

    Ok, der Screenshot schreit nach UserControl (UC)-Einsatz, der sinnvoll wäre. Und jedes UC sollte eine Tank-Klasseninstanz beherbergen/verwalten.
    Falls Du mit den Begriffen was anfangen kannst und wüsstest, wie das umzusetzen ist.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo VaporiZed

    Ich habe einen Beitrag von 2011 einem User Namens X-Zat gefunden der "[HOW TO] Eigene Klassen erstellen, verwalten und verwenden" erklärt.
    Sehe ich mir an.
    Bezüglich UserControl habe ich noch nichts gefunden.

    Aber Danke für deinen Tipp.

    Gruß Gebhard
    Ein UserControl ist ein zusammengesetztes Control. Da kannst Du dann eben ein paar Labels und TextBoxen und Buttons usw. draufhauen. Und dann eben drei dieser UserControls auf Dein Form hauen. Und schon hast Du drei gleich aussehende "Blöcke" für Tank1, Tank2 und Tank3. Erleichtert die Datenverarbeitung sehr. Weil nicht alles auf dem MainForm ist. Anordnen lassen die sich dann auf dem MainForm ganz gut z.B. mit einem FlowLayoutPanel oder TableLayooutPanel.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Typhoon schrieb:

    Um es kurz zu machen für einen Eintrag in eine DB wie im Bild unten gibt es einfachere Methoden wie von euch beschrieben.
    Glaub ich nicht.
    Und wenn doch dann allenfalls mit unzureichender Leistungsfähigkeit.
    Was nützt es, Einträge machen zu können, wenn fehlt, sie wieder abrufen zu können?
    Und bei Fehl-Eingaben muss man auch Ändern können, oder Löschen.

    Typhoon schrieb:

    Um nicht unverschämt zu sein gibt es beispiele im Netz die so etwas schon einmal behandelt haben?
    Ich hab paar Tuts zum Thema gemacht (auf eines hab ich dich ja schon hingewiesen), allerdings beschäftige ich mich an keiner Stelle nur mit "Einträge machen".
    Wie gesagt: Wenn man nicht auch Abrufen, Ändern und Löschen kann ist die Technologie unvollständig.
    Ich würde das anders lösen:

    Ein DataSet erstellen, danach ein Datenmodell. Da gäbe es bei mir eine Tank-Tabelle und eine Messung-Tabelle, die mit der Tank-Tabelle verknüpft ist.
    Deine Form als Dialog aufrufen und beim Schließen mit OK (DialogResult = OK) würden bei mir dann 3 MessungRows hinzugefügt, mit jeweils
    den Werten, die eingetragen wurden. Mit dem Abspeichern kümmert sich der DataAdapter automatisch um die Übertragung an die Datenbank.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Moinsen!

    Mal als Tip: Beschäftige Dich mal mit der Trennung von Oberfläche, Geschäftslogik und Datenzugriffslogik. Macht sich auch bei vermeintlich kleinen Projekten gut (merke: kleine Projekte neigen gerne zum wachsen ;) )

    Datasets kann man machen, ich bevorzuge aber lieber SPs in der jeweiligen Datenbank. Ein handgeschriebenes SQL ist zwar etwas aufwendiger, liefert aber bei nicht trivialen Zugriffen i.d.R. die besseren Ergebnisse.

    Aber zunächst: Beschäftige Dich mal mit sauberer Typisierung, der Erstellung und Verwendung von Klassen und einem sauberen Programmaufbau. Meiner Meinung nach gibt es z.B. nur sehr wenige Gründe, Module in einem VB-Programm zu haben (z.B. wenn man "My" erweitern möchte)

    Viele Grüße

    Gerrit
    Hallo zusammen

    Danke für eure Tipps und Hinweise.

    @VaporiZed, tragl

    Ich habe mir das Thema DataSet bzw. UserControl einmal angeschaut. Leider bin ich nicht schlau geworden. Liegt ganz sicher an mir.

    @Gerrit

    Ein handgeschriebenes SQL ist zwar etwas aufwendiger, liefert aber bei nicht trivialen Zugriffen i.d.R. die besseren Ergebnisse.


    Da ich schon eine Vorlage diesbezüglich habe bin ich deiner Meinung.

    Ich habe jetzt ein "Grundstock" gebaut der funktioniert. 3 Werte werden in die DB geschrieben mit Datum als Primärschlüssel.
    Wäre es möglich, das Du (Gerrit) einmal über "code" darüberfliegt und gegebenenfalls Verbesserungsvorschläge machen kann?

    Beschäftige Dich mal mit sauberer Typisierung, der Erstellung und Verwendung von Klassen und einem sauberen Programmaufbau.


    Das ist bis jetzt meine Mappe.



    Grüße und ein schönes Wochenende euch allen!!

    Gebhard
    Moinsen,

    Typhoon schrieb:

    Ich habe jetzt ein "Grundstock" gebaut der funktioniert. 3 Werte werden in die DB geschrieben mit Datum als Primärschlüssel.


    Wenn Du schon um Verbesserungen bittest... ^^

    Bist Du Dir sicher, daß es NIE vorkommen kann, daß es zwei Meßwerte mit gleichem Zeitstempel geben kann? Wenn nicht, dann ist Dein Primärschlüssel ungeeignet. Weiterhin: Sind Deine Zeitstempel UTC oder Ortszeit? Wenn Ortszeit: Probleme sind im Frühjahr und Herbst vorprogrammiert. Kleiner Tip von mir: Ich nutze als Primärschlüssel fast immer einen fortlaufenden Integer. Weitere Einschränkungen laufen dann über eindeutige Indizes etc. Ist zwar u.U. ein Feld mehr, macht aber die Verwaltung und auch das Debuggen einfacher.

    Typhoon schrieb:

    Wäre es möglich, das Du (Gerrit) einmal über "code" darüberfliegt und gegebenenfalls Verbesserungsvorschläge machen kann?


    Möglich schon. Ich stecke aber gerade in einem ziemlich großen Projekt. Mal sehen, wie es mit der Zeit aussieht. Außerdem (wenn ich's nicht übersehen habe: Wo ist der Code?)

    Typhoon schrieb:

    Beschäftige Dich mal mit sauberer Typisierung, der Erstellung und Verwendung von Klassen und einem sauberen Programmaufbau.


    Das ist bis jetzt meine Mappe.


    Äh --- nein. Typisierung hat nichts mit dem Aufbau Deiner Projektmappe zu tun sondern damit, alle Variablen und Parameter sauber mit einem passenden Datentyp zu definieren und implizite Typumwandlung zu vermeiden (Grundeinstellung: OPTION EXPLICIT ON, OPTION STRICT ON)

    Hier mal ein kleiner Vorgeschmack an Hand einer katastrophalen Codezeile Deines Eingangsbeitrages (hab ich mal ungetestet auf die Schnelle zusammengeschreibselt)

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Aufzhäung der mögl. Filterwechsel (brauchen wir gleich noch weiter unten)
    3. ''' </summary>
    4. ''' <remarks></remarks>
    5. Public Enum TankFilterEnum As Integer
    6. KeinWechsel = 0
    7. FilterKlein = 1
    8. FilterGross = 2
    9. End Enum
    10. ''' <summary>
    11. ''' Datenklasse mit Meßwerten eines Tanks (brauchen wir gleich noch weiter unten).
    12. ''' </summary>
    13. ''' <remarks>
    14. ''' Ist hier nur rudimentär, kann man noch aufbohren zum direkten Schreiben/Lesen etc.
    15. ''' </remarks>
    16. Public Class clsMesswert
    17. Private _TankNr As Int32 = 0
    18. Private _Zeitpunkt As DateTime
    19. Private _Leitwert As Decimal
    20. Private _phWert As Decimal
    21. Private _Temperatur As Decimal
    22. Private _FilterWechsel As TankFilterEnum = TankFilterEnum.KeinWechsel
    23. Private _Reingung As DateTime
    24. ''' <summary>
    25. ''' Nummer des Tanks
    26. ''' </summary>
    27. ''' <value></value>
    28. ''' <returns></returns>
    29. ''' <remarks></remarks>
    30. Public Property TankNr() As Int32
    31. Get
    32. Return _TankNr
    33. End Get
    34. Set(ByVal value As Int32)
    35. If value < 0 Then
    36. value = 0
    37. End If
    38. _TankNr = value
    39. End Set
    40. End Property
    41. ''' <summary>
    42. ''' Zeitpunkt der Messung als UTC
    43. ''' </summary>
    44. ''' <value></value>
    45. ''' <returns></returns>
    46. ''' <remarks></remarks>
    47. Public Property ZeitpunktUTC() As DateTime
    48. Get
    49. Return ZeitpunktUTC
    50. End Get
    51. Set(ByVal value As DateTime)
    52. Select Case value.Kind
    53. Case DateTimeKind.Unspecified
    54. value = DateTime.SpecifyKind(value, DateTimeKind.Local).ToUniversalTime
    55. Case DateTimeKind.Local
    56. value = value.ToUniversalTime
    57. End Select
    58. _Zeitpunkt = value
    59. End Set
    60. End Property
    61. ''' <summary>
    62. ''' Leitwert der Flüssigkeit zum Meßzeitpunkt
    63. ''' </summary>
    64. ''' <value></value>
    65. ''' <returns></returns>
    66. ''' <remarks></remarks>
    67. Public Property Leitwert() As Decimal
    68. Get
    69. Return _Leitwert
    70. End Get
    71. Set(ByVal value As Decimal)
    72. Select Case value
    73. Case Is < 0D 'Hier zulässige Eingabegrenzen festlegen (Minimum)
    74. value = 0D
    75. Case Is > 99.99D 'Hier zulässige Eingabegrenzen festlegen (Maximum)
    76. value = 99.99D
    77. End Select
    78. _Leitwert = value
    79. End Set
    80. End Property
    81. ''' <summary>
    82. ''' PH-Wert der Flüssigkeit zum Meßzeitpunkt
    83. ''' </summary>
    84. ''' <value></value>
    85. ''' <returns></returns>
    86. ''' <remarks></remarks>
    87. Public Property PhWert() As Decimal
    88. Get
    89. Return _phWert
    90. End Get
    91. Set(ByVal value As Decimal)
    92. Select Case value
    93. Case Is < 0D 'Hier zulässige Eingabegrenzen festlegen (Minimum)
    94. value = 0D
    95. Case Is > 14D 'Hier zulässige Eingabegrenzen festlegen (Maximum)
    96. value = 14D
    97. End Select
    98. _phWert = value
    99. End Set
    100. End Property
    101. ''' <summary>
    102. ''' Temperatur der Flüssigkeit zum Meßzeitpunkt in Grad Celsius
    103. ''' </summary>
    104. ''' <value></value>
    105. ''' <returns></returns>
    106. ''' <remarks></remarks>
    107. Public Property Temperatur() As Decimal
    108. Get
    109. Return _Temperatur
    110. End Get
    111. Set(ByVal value As Decimal)
    112. Select Case value
    113. Case Is < -273.14D 'Hier zulässige Eingabegrenzen festlegen (Minimum)
    114. value = - 273.14D
    115. Case Is > 250D 'Hier zulässige Eingabegrenzen festlegen (Maximum)
    116. value = 250D
    117. End Select
    118. _Temperatur = value
    119. End Set
    120. End Property
    121. Public Property Filterwechsel() As TankFilterEnum
    122. Get
    123. Return _FilterWechsel
    124. End Get
    125. Set(ByVal value As TankFilterEnum)
    126. _FilterWechsel = value
    127. End Set
    128. End Property
    129. ''' <summary>
    130. ''' Zeitpunkt der letzten Reinigung (Jahr &lt;2010 = keine Reingung)
    131. ''' </summary>
    132. ''' <value></value>
    133. ''' <returns></returns>
    134. ''' <remarks></remarks>
    135. Public Property ReinigungUTC() As DateTime
    136. Get
    137. Return _Reingung
    138. End Get
    139. Set(ByVal value As DateTime)
    140. Select Case value.Kind
    141. Case DateTimeKind.Unspecified
    142. value = DateTime.SpecifyKind(value, DateTimeKind.Local).ToUniversalTime
    143. Case DateTimeKind.Local
    144. value = value.ToUniversalTime
    145. End Select
    146. _Reingung = value
    147. End Set
    148. End Property
    149. End Class
    150. Public Class Beispiel
    151. 'Das ist Mist.
    152. 'Public Function SchreibeMessung(ByVal myDate, ByVal myTime, ByVal myLeitwertTank1, ByVal myphWertTank1, ByVal myTemperaturTank1, ByVal myFilterTank1, ByVal myReinigungTank1, ByVal myLeitwertTank2, ByVal myphWertTank2, ByVal myTemperaturTank2, ByVal myFilterTank2, ByVal myReinigungTank2, ByVal myLeitwertTank3, ByVal myphWertTank3, ByVal myTemperaturTank3, ByVal myFilterTank3, ByVal myReinigungTank3)
    153. 'End Function
    154. ''' <summary>
    155. ''' Schreibt eine Messung in die Datenbank
    156. ''' </summary>
    157. ''' <param name="myDate">Datum der Messung</param>
    158. ''' <param name="myTime">Uhrzeit der Messung (warum zwei Variablen?)</param>
    159. ''' <param name="myLeitwertTank1">Leitwert</param>
    160. ''' <param name="myphWertTank1">Ph-Wert</param>
    161. ''' <param name="myTemperaturTank1">Temperatur</param>
    162. ''' <param name="myFilterTank1">Filterwechsel (0 = keiner, 1 = klein, 2 = groß)</param>
    163. ''' <param name="myReinigungTank1">Zeitpunkt der letzten Reinigung</param>
    164. ''' <param name="myLeitwertTank2">Leitwert</param>
    165. ''' <param name="myphWertTank2">Ph-Wert</param>
    166. ''' <param name="myTemperaturTank2">Temperatur</param>
    167. ''' <param name="myFilterTank2">Filterwechsel (0 = keiner, 1 = klein, 2 = groß)</param>
    168. ''' <param name="myReinigungTank2">Zeitpunkt der letzten Reinigung</param>
    169. ''' <param name="myLeitwertTank3">Leitwert</param>
    170. ''' <param name="myphWertTank3">Ph-Wert</param>
    171. ''' <param name="myTemperaturTank3">Temperatur</param>
    172. ''' <param name="myFilterTank3">Filterwechsel (0 = keiner, 1 = klein, 2 = groß)</param>
    173. ''' <param name="myReinigungTank3">Zeitpunkt der letzten Reinigung</param>
    174. ''' <returns></returns>
    175. ''' <remarks></remarks>
    176. Public Function SchreibeMessung( _
    177. ByVal myDate As DateTime _
    178. , ByVal myTime As DateTime _
    179. , ByVal myLeitwertTank1 As Decimal _
    180. , ByVal myphWertTank1 As Decimal _
    181. , ByVal myTemperaturTank1 As Decimal _
    182. , ByVal myFilterTank1 As Int32 _
    183. , ByVal myReinigungTank1 As DateTime _
    184. , ByVal myLeitwertTank2 As Decimal _
    185. , ByVal myphWertTank2 As Decimal _
    186. , ByVal myTemperaturTank2 As Decimal _
    187. , ByVal myFilterTank2 As Int32 _
    188. , ByVal myReinigungTank2 As DateTime _
    189. , ByVal myLeitwertTank3 As Decimal _
    190. , ByVal myphWertTank3 As Decimal _
    191. , ByVal myTemperaturTank3 As Decimal _
    192. , ByVal myFilterTank3 As Int32 _
    193. , ByVal myReinigungTank3 As DateTime _
    194. ) As Boolean
    195. 'So wie man Deine Funktion sauber Typisiert aufbauen müßte
    196. 'Ob die Variablentypen so passen kann ich nicht sagen.
    197. End Function
    198. ''' <summary>
    199. ''' Schriebt eine Meßreihe in die Datenbank
    200. ''' </summary>
    201. ''' <param name="Messwerte">Meßwerte der einzelnen Tanks. Schlüssel ist die Tanknummer!</param>
    202. ''' <returns>WAHR wenn fehlerfreie Ausführung, ansonsten FALSCH</returns>
    203. ''' <remarks>Hier nur zur Demonstrataion</remarks>
    204. Public Function SchreibeMessung( _
    205. ByVal Messwerte As Dictionary(Of Int32, clsMesswert) _
    206. ) As Boolean
    207. 'So wie man es eleganter machen kann.
    208. 'Anmerkung: Der Schlüssel (Int32) ist die Tanknummer
    209. SchreibeMessung = True
    210. If Messwerte Is Nothing Then
    211. Return False
    212. End If
    213. For Each KPV As KeyValuePair(Of Int32, clsMesswert) In Messwerte
    214. 'Hier verarbeiten
    215. Next
    216. End Function
    217. End Class


    Code sollte immer sauber kommentiert sein. ;)

    Viele Grüße

    Gerrit

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