Καταρχήν, καλό είναι ο τίτλος του post να έχει σχέση με αυτό που πραγματικά ρωτάς, γιατί έτσι είναι πολύ πιθανότερο να πάρεις έγκαιρη απάντηση. Στην περίπτωση σου θα ήταν καλύτερο να είχες βάλει τίτλο "Πρόβλημα σύνδεσης σε SQL Server".
Όσον αφορά το πρόβλημα σου, έχεις ανοίξει τη σύνδεση αλλά δεν την έχεις περάσει στο command. Οπότε δεν έχει σύνδεση για να εκτελεστεί. Αν προσθέσεις τη γραμμή OleDbCommand.Connection = SQLConn πριν την ExecuteScalar, θα δουλέψει. Θα πρέπει όμως να έχεις υπόψη ότι ο κώδικας σου έχει αρκετά προβλήματα.
- Χρησιμοποιείς τις κλάσεις του OLEDB provider του SQL Server αντί για τον .ΝΕΤ provider ο οποίος είναι αρκετά πιο γρήγορος και εύκολος στη χρήση
- Δημιουργείς και εκτελείς ένα SQL string, κάτι που δημιουργεί προβλήματα ασφάλειας και ταχύτητας. Μπορεί πχ. ο χρήστης να δώσει ένα περίεργο string, κάτι σαν "; xp_cmdshell 'format c:'". Αυτό λέγεται SQL Injection attack, αλλά είναι απίστευτα εύκολο να το αποφύγεις στον SQL Server. Αντί να φτιάξεις ένα χύμα sql string μπορείς να χρησιμοποιήσεις παραμέτρους. Επιπλέον, ο SQL Server διατηρεί τα execution plans (τα compiled queries ας πούμε) και μπορεί να τα ξαναχρησιμοποιήσει. Τα χύμα queries πρέπει να τα κάνει ξανά compile κάθε φορά.
- Αντί να ανοίγεις και να κλείνεις το connection με το χέρι, μπορείς να χρησιμοποιήσεις τη Using για να κλείσει το connection αυτόματα. Διαφορετικά, σε περίπτωση exception το connection θα μείνει ανοικτό.
- Αντί να ορίζεις σε μία γραμμή τη μεταβλητή και μετά να θέτεις την τιμή της, καλύτερα να τα κάνεις όλα σε μία γραμμή. Έτσι αποφεύγεις την ύπαρξη μισο-φτιαγμένων μεταβλητών στον κώδικα σου. Όσο προσεκτικός να είσαι, κάποια στιγμή, στις 3 το πρωί, θα προσπαθήσεις να χρησιμοποιήσεις μία μεταβλητή η οποία δεν έχει ετοιμαστεί πλήρως.
Θα μπορούσες να ξαναγράψεις τον κώδικα σου ως εξής:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim AFM As String
Dim query As String = "SELECT AFM FROM CUSTOMER WHERE AFM = @AFM"
Using myConnection As New SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=MyDatabase;User ID=AAAAAA;Password=XXXXXX")
Using myCommand = New SqlCommand(query, myConnection)
myCommand.Parameters.AddWithValue("@AFM", TextBox1.Text)
myConnection.Open()
AFM = CStr(myCommand.ExecuteScalar())
MessageBox.Show(String.Format("AFM = {0}", AFM))
End Using
End Using
End Sub
Χρησιμοποιώ την String.Format στο τέλος για να αποφύγω τη δημιουργία περιττών string. Σε αυτή την περίπτωση δεν γλυτώνω και πολλά, αλλά αν είχα κάτι σαν "AFM = " & AFM & " Name = " & Name, θα δημιουργούνταν και καταστραφούν 2 temporary strings κάθε φορά που θα εκτελούσα τον κώδικα (ένα κάθε φορά που προσθέτω μία μεταβλητή). Ενώ θα μπορούσα με την String.Format("AFM - {0} Name={1}",AFM,Name) να κάνω την ίδια δουλειά χωρίς να δημιουργηθεί κανένα temporary string.
Ένα πρόβλημα που υπάρχει ακόμα είναι ότι το connection string βρίσκεται μέσα στον κώδικα σου, με αποτέλεσμα για κάθε αλλαγή να πρέπει να πειράξεις τον κώδικα σου. Μπορείς αντί γι αυτό να αποθηκεύσεις το Connection String στα application settings της εφαρμογής σου π.χ. με το όνομα MyDB και να χρησιμοποιείς το My.Settings.MyDB αντί για ολόκληρο το string. Άνοιξε το My Project του project σου και πήγαινε στο tab Settings. Εκεί πρόσθεσε το MyDB με τύπο Connection String (είναι στο τέλος). Στη στήλη value βάζεις το connection string ή χρησιμοποιείς τον connection builder (το κουμπί "...") για να φτιάξεις ένα νέο.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos