Announcement

Collapse
No announcement yet.

Datarow.ToString

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Datarow.ToString

    Hallo,
    habe folgende Ausgangssituation. Ich sende ein Dataset als XML-String (inklusiv Schema) von einer Desktopanwendung an eine ganz normale ASPX-Site. Dort lese ich den XML-String wieder in ein Dataset ein. Auf dem Server läuft MSSQL Express 2005. Dort sollen Daten aktualisiert werden. Nehmen wir den Fall neue Daten einfügen. Ich durchlaufe also alle Tabellen im Dataset und dann alle Zeilen in der jeweiligen Tabelle. Für jede Zeile generiere ich dann eine Insert-Anweisung und führe die Anweisung über ein SqlCommand aus. Das klappt alles wunderbar. Das einzige Problem sind die Decimal-Felder. Der VALUES Teil der Insert-Anweisung wird so zusammengebaut:
    - der colstr wird vorher aus den Feldnamen zusammengebaut

    Code:
                Dim sql As New StringBuilder(1000)
                sql.Append("insert into " & tab.TableName)
                sql.Append(" (" & colstr.ToString & ") VALUES ('")
    
                dim  valstr as New StringBuilder(100)
                valstr.Append(row(0) & "','")
                For i = 1 To tab.Columns.Count - 2
                         valstr.Append(row(i) & "','")
                Next
                valstr.Append(row(tab.Columns.Count - 1))
                sql.Append(valstr.ToString & "')")
                cmd.CommandText = sql.ToString
                cmd.Connection.Open()
    Heraus kommt eine funktionierende SQL-Anweisung. Nur wenn row(i) ein decimal ist, dann steht in der SQL-Anweisung nicht '3.99' sondern '3,99'. Was dann in der Datenbank steht könnt ihr euch wohl vorstellen (nicht 3,99 € sondern 3990,00 €). Eine mögliche Lösung wäre natürlich jedes Feld auf seinen Type zu testen und im Falle von decimal bei der Ausgabe das ',' durch den '.' zu ersetzen. Das finde ich allerdings recht unelegant. Hat vielleicht von euch jemand eine elegantere Idee? Vielen Dank im Voraus.
    Conny

    PS: eventuell passt der Titel nicht ganz zum Problem

  • #2
    Wenn gleich mehrere Zeilen einer Tabelle in die Datenbank übertragen werden sollen, dann sollte ein Sql-Statement verwendet werden, dass DbParameter verwendet (mehrere Zeilen können in einem RoundTrip geschrieben werden). Ein DbParameter muss zum DataType der DataColumn passen, eine Unterscheidung der DataTypes ist demnach nicht zu vermeiden.
    Auch im bisherigen Konzept ist mindestens der Type String gesondert zu behandeln, da einzelne Hochkommata (') innerhalb von Strings zu einem Sql-Ausdruck mit unabsehbaren Folgen führen;
    Abhilfe: Replace("'", "''").
    Anmerkung: unter Verwendung von DbParametern ist ein derartiges Replace() nicht nötig.
    Im vorgestellten Code müsste ebenfalls berücksichtigt werden, dass innerhalb einer Zelle ein System.DbNull.Value enthalten sein könnte.
    Allgemein können Konvertierungen auch unter Angabe eines FormatProviders vorgenommen werden, z.B. wird per Convert.ChangeType(obj, GetType(String), System.Globalization.CultureInfo.InvariantCulture) ein Dezimalpunkt verwendet, Datumsangaben werden im amerikanischen Datumsformat präsentiert.

    Comment


    • #3
      Hallo AKK,
      vielen Dank für die Hinweise. Das mit den Hochkommas ist mir auch eingefallen. Was das SQL-Statement mit DbParameter angeht, magst Du recht haben. Allerdings muß man dann für jede Tabelle ein solches Statement erstellen. Kommt eine neue Tabelle hinzu, muß man für diese ein SQL-Statement erstellen. Da finde ich folgenden Code doch flexibler:

      Code:
        Sub update_Table(ByVal tab As DataTable)
              'aktualisiert Daten in der Tabelle 'tab'
              Dim cmd As New SqlCommand
              Dim con As New SqlConnection(Me.ArtikelSqlDataSource.ConnectionString)
              Dim colstr As New StringBuilder(100)
              Dim zeilenOK As Integer = 0
              Dim val As String = ""
      
              cmd.Connection = con
              For Each row As DataRow In tab.Rows
                  Dim sql As New StringBuilder(1000)
                  sql.AppendLine("update " & tab.TableName & " set")
                  For i = 0 To tab.Columns.Count - 2
                      val = row(i)
                      If tab.Columns(i).DataType.FullName = "System.Decimal" Then
                          val = Replace(val, ",", ".")
                      End If
                      sql.AppendLine(tab.Columns(i).ColumnName & "='" & val & "',")
                  Next
                  sql.AppendLine(tab.Columns(tab.Columns.Count - 1).ColumnName & "='" & row(tab.Columns.Count - 1) & "'")
                  sql.Append("where " & tab.PrimaryKey(0).ColumnName & "=" & row(tab.PrimaryKey(0).ColumnName))
                  cmd.CommandText = sql.ToString
                  cmd.Connection.Open()
                  Try
                      zeilenOK += cmd.ExecuteNonQuery()
                  Catch ex As Exception
                      write_Error(ex.Message)
                  End Try
                  cmd.Connection.Close()
              Next
              write_Data(zeilenOK & " von " & tab.Rows.Count & " Zeilen in Tabelle " & tab.TableName & " aktualisiert")
          End Sub
      Natürlich nur wenn die Tabellenstrukturen kompatibel sind.
      Den Fall DBNULL habe ich bereits vor dem Transfer der Daten zum Server behandelt, indem alle DBNULL-Werte mit dem Typ entsprechenden Default-Werten ersetzt werden.
      Vielen Dank noch einmal.
      Conny

      Comment

      Working...
      X