2016-12-26 3 views
0

Ich habe diese Stunden lang gehämmert, aber habe es nicht richtig verstanden, also habe ich beschlossen, zu posten.Vb.NET MS Access SQL AKTUALISIEREN Syntax Ausgabe

Meine Vb.NET App hat 2 Jpgs auf der Festplatte. Einer ist LowRes und der andere ist HighRes. Ich möchte beide Bilder in dem gleichen Datensatz in einer Microsoft Access 2007-Datenbank über INSERT speichern, die einwandfrei funktioniert, und dann UPDATE, um den zweiten hinzuzufügen. Die UPDATE funktioniert nicht.

Ich habe einen Haufen Code zusammengefügt, den ich online für den INSERT Code gefunden habe (so wie ich es gelernt habe) und irgendwann herausgefunden, dass das tatsächlich funktioniert hat. Es ist jedoch schwierig, die Funktion zu optimieren, um ein UPDATE durchzuführen, um das zweite Bild hinzuzufügen. Ich vermute, dass es etwas damit zu tun hat, Parameter falsch anzugeben?

Die Datenbank verfügt über 1 Tabelle Records mit 3 Spalten RecordID (der Text ist, und einen Autowert Primärschlüssel, die von Form1.Tb_RecordID.Text gezogen wird), HighRes (die OLE) zur Verfügung und LowRes (Welche OLE ist auch). Die Datenbank heißt Database.accdb.

Ich nenne das Unterprogramm mit:

Save_To_Database("LowProfile.jpg", "LowRes") 

wenn ich es INSERT ein OLE-Bild in dem "LowRes" -Spalte will. Ich nenne dann

Update_To_Database("HighProfile.jpg", "HighRes") 

den Datensatz mit dem HighRes Bild zu aktualisieren. Ich möchte schließlich diese Funktionen eins zu eins konsolidieren und ByVals verwenden, um festzustellen, ob es Aktualisieren oder Einfügen sollte.

Dies funktioniert:

Sub Save_To_Database(ByVal Filename As String, ByVal Res As String) 

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb" 
    Dim theQuery As String = "INSERT INTO Records([RecordID],[" & Res & "]) values (" & Form1.Tb_RecordID.Text & ", @Img)" 

    Try 
     Dim fs As FileStream 
     fs = New FileStream(Filename, FileMode.Open, FileAccess.Read) 
     Dim picByte As Byte() = New Byte(fs.Length - 1) {} 
     fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length)) 
     fs.Close() 
     Dim CN As New OleDbConnection(cnString) 
     CN.Open() 
     Dim imgParam As New OleDbParameter() 
     imgParam.OleDbType = OleDbType.Binary 
     imgParam.ParameterName = "Img" 
     imgParam.Value = picByte 
     Dim cmd As New OleDbCommand(theQuery, CN) 
     cmd.Parameters.Add(imgParam) 
     cmd.ExecuteNonQuery() 
     MessageBox.Show("Image successfully saved.") 
     cmd.Dispose() 
     CN.Close() 
     CN.Dispose() 
    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 

End Sub 

jedoch mein UPDATE Code schlägt mit Syntaxfehler auf der SQL-Anweisung:

Sub Update_To_Database(ByVal Filename As String, ByVal Res As String) 

    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb" 
    Dim theQuery As String = "UPDATE Records SET ([" & Res & "]) values (@Img) WHERE RecordID =" & Form1.Tb_RecordID.Text 

    MsgBox(theQuery) 

    Try 
     Dim fs As FileStream 
     fs = New FileStream(Filename, FileMode.Open, FileAccess.Read) 
     Dim picByte As Byte() = New Byte(fs.Length - 1) {} 
     fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length)) 
     fs.Close() 
     Dim CN As New OleDbConnection(cnString) 
     CN.Open() 
     Dim imgParam As New OleDbParameter() 
     imgParam.OleDbType = OleDbType.Binary 
     imgParam.ParameterName = "Img" 
     imgParam.Value = picByte 
     Dim cmd As New OleDbCommand(theQuery, CN) 
     cmd.Parameters.Add(imgParam) 
     cmd.ExecuteNonQuery() 
     MessageBox.Show("Image successfully saved.") 
     cmd.Dispose() 
     CN.Close() 
     CN.Dispose() 
    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 

End Sub 

Wer das Problem? Oder eine Möglichkeit, den Code zu verbessern?

+0

Verwendung so etwas wie dieses 'UPDATE Aufzeichnungen SET ([ "& Res &"]) = @Img WHERE' – Abhay

+0

ich diesen Thread gefunden: Tinyurl.com/hkjwtwz und mag wirklich, wie er structued seine SQL und sogar, wie es prüft, ob der Datensatz existiert. Ich versuche, es zu ändern, um so etwas zu tun, aber ich weiß nicht, was mit imgParam oder fs zu tun ist. –

+0

Auch Abhay. Es wirft immer noch einen Syntaxfehler auf. Ich habe eine Msgbox gemacht, um den String zu sehen und er sagt: "UPDATE Records SET ([HighRes]) = @img WHERE RecordID = 1" wenn das hilft. –

Antwort

0

Ihr ursprüngliches Problem ist die Tatsache, dass Sie versucht haben, eine Update-Anweisung mit der Syntax einer Insert-Anweisung zu schreiben. Eine einfache Lösung wäre einfach, die Update-Anweisung in die richtige Syntax zu ändern.

Allerdings gibt es eine Reihe von Dingen in Ihrem Code, der sein könnte und sollte geändert werden, so schrieb ich ein Beispiel basierend auf dem Code, der kann noch weiter verbessert werden:

Sub Save_To_Database(ByVal Filename As String, ByVal RecordId As String, ByVal IsHighResolution As Boolean, ByVal IsNew As Boolean) 

    Dim theQuery As String 
    Dim cnString As String = "PROVIDER=Microsoft.ACE.OLEDB.12.0;Data Source=Database.accdb" 

    If IsNew Then 
     theQuery = "INSERT INTO Records([RecordID],[" & IIf(IsHighResolution, "HighRes", "LowRes") & "]) values (@RecordId, @Img)" 
    Else 
     theQuery = "UPDATE Records SET " & IIf(IsHighResolution, "HighRes", "LowRes") & " = @Img WHERE RecordID = @RecordId" 
    End If 

    Try 
     Using fs As New FileStream(Filename, FileMode.Open, FileAccess.Read) 
      Dim picByte As Byte() = New Byte(fs.Length - 1) {} 
      fs.Read(picByte, 0, System.Convert.ToInt32(fs.Length)) 
      Using CN As New OleDbConnection(ConnectionString) 

       Dim cmd As New OleDbCommand(theQuery, CN) 
       cmd.Parameters.Add("Img", OleDbType.Binary).Value = picByte 
       cmd.Parameters.Add("@RecordId", OleDbType.Integer).Value = RecordId 

       CN.Open() 
       cmd.ExecuteNonQuery() 
       MessageBox.Show("Image successfully saved.") 
      End Using 
     End Using 

    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 

End Sub 

Points of Interest:

  1. Insert und Update jetzt mit dem gleichen Verfahren behandelt wird, ist nur Unterschied ein boolescher Parameter, der angibt, ob dies ein neuer Datensatz ist oder eine vorhandene.

  2. Abfragen sind jetzt sicher vor SQL-Injektion. Die einzige Verkettung hier ist der Spaltenname, den Sie in sql nicht parametrisieren können, aber er wird innerhalb des Subs selbst entschieden. Wenn Sie das Sub verwenden, übergeben Sie nur einen booleschen Wert, der angibt, dass es sich um ein Bild mit hoher Auflösung handelt.

  3. Der Block Using wird empfohlen, wenn Sie etwas verwenden, das die IDisposable-Schnittstelle implementiert. Dies gewährleistet die korrekte Annäherung und Entsorgung auch im Falle einer Ausnahmebedingung.

  4. Parametercode vereinfacht.

+0

Sie haben mich auf einige Verbesserungen gebracht, die ich mir vorgestellt habe, wie zum Beispiel das Einfügen von byVals und die If-Anweisung für die Abfrage sowie das Setzen der Record ID als Parameter. Ich weiß nichts über IIF und werde es notieren. Auch sieht es viel besser aus. Ich habe immer noch nicht den Sinn, noch zu benutzen. Ich werde es morgen testen. Nächstes Projekt ist herauszufinden, wie man das liest und die entsprechenden Picture Boxes füllt. –

+0

Ok, also habe ich es versucht und es wirft einen Fehler auf die INSERT-Anweisung, aber sagt, die UPDATE-Anweisung war erfolgreich, obwohl keine Datensätze/Informationen in die Datenbank geschrieben werden. Es hat erfolgreich nichts aktualisiert. Ich gebe den Fehler: "Datentyp stimmt nicht mit Kriterienausdruck überein." Ich habe meine alte verkettete INSERT-Anweisung versucht, und es funktioniert gut, was mich denken lässt, dass der Parameter @RecordId Probleme hat. I CInt die RecordID, wenn ich das Sub aufrufen, änderte ich ByVal zu Integer, und es gibt immer noch den Fehler. Ich vermisse etwas. –

+0

Auch RecordID wird durch eine autonumber Sequenz erstellt und aus einem deaktivierten und schreibgeschützten Feld gelesen, ich bezweifle, dass es für jede Art von SQL Injection .... anfällig wäre/wäre. –