To all, I am learning Visual Basic and I am currently working on a Windows Application. I have two text box methods (usernameTextBox, passwordTextBox). In which the user will enter data and then hit the submit button (Button1_Click). That method will call connect. What I want to be able to do, is to have the user type-in their username and password. Then it is passed by value, not reference into connect() when it is invoked inside the Button method.
Kind of like an authentication page. Now I have values in connect(FirstName:="JohnDoe", Password:="password") - this is basically for testing MySQL server and for demonstration of what I am trying to attempt.
Imports MySql.Data.MySqlClient
Public Class SecurePasswordList
Dim conn As New MySqlConnection
Public Sub connect(ByVal FirstName As String, ByVal Password As String)
Dim DatabaseName As String = "mysql"
Dim server As String = "10.1.0.0"
If Not conn Is Nothing Then conn.Close()
conn.ConnectionString = String.Format("server={0}; user id={1}; password={2}; database={3}; pooling=false", server, FirstName, Password, DatabaseName)
Try
conn.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
conn.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
connect(FirstName:="JohnDoe", Password:="password")
End Sub
Private Sub SecurePasswordList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub usernameTextBox_TextChanged(sender As Object, e As EventArgs) Handles usernameTextBox.TextChanged
Dim FirstName As String
FirstName = usernameTextBox.Text
End Sub
Private Sub passwordTextBox_TextChanged(sender As Object, e As EventArgs) Handles passwordTextBox.TextChanged
Dim Password As String
Password = passwordTextBox.Text
End Sub
End Class
Change
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
connect(FirstName:="JohnDoe", Password:="password")
End Sub
to
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
connect(FirstName, Password)
End Sub
but you should ensure that FirstName and Password are initialized AND held as class variables.
Move
Dim FirstName As String
Dim FirstName As String
to be in the class, not the event handling functions (Click etc). Like this:
Public Class SecurePasswordList
Dim conn As New MySqlConnection
Dim FirstName As String
Dim FirstName As String
BUT really you can redo your code like this (as all you want is the Text from the controls):
Imports MySql.Data.MySqlClient
Public Class SecurePasswordList
Dim conn As New MySqlConnection
Public Sub connect(ByVal FirstName As String, ByVal Password As String)
Dim DatabaseName As String = "mysql"
Dim server As String = "10.1.0.0"
If Not conn Is Nothing Then conn.Close()
conn.ConnectionString = String.Format("server={0}; user id={1}; password={2}; database={3}; pooling=false", server, FirstName, Password, DatabaseName)
Try
conn.Open()
Catch ex As Exception
MsgBox(ex.Message)
End Try
conn.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
connect(usernameTextBox.Text, passwordTextBox.Text)
End Sub
End Class
I dont think passing by value or reference is the issue here. Do you want the connect function to modify the strings passed into it? I doubt it. So in that case Value or reference is fine. Strings are passed by a copied instance by reference, so in effect they are passed by Value unless you use Byref in the function declaration which will. Every class (int, string, etc) are passed differently in VB by default. You need to check each type to know what it will do if you specify Byval or Byref. String creates a copy of the String if you use Byval, but is actually accessed using the pointer to the newly created String. So it depends how deep you want to dig too
Related
I have the code written to connect to the ODBC registry.
The database name is written to the combobox.
I need to transfer my ip address and password from ODBC.ini to the connect string after selecting the database from the combobox.
This is a connection to MYSQL.
Thank you
Private Sub DsnLookup()
Dim dsnNames As New List(Of String)
Dim reg As Microsoft.Win32.RegistryKey = Registry.CurrentUser.OpenSubKey("Software")
If reg IsNot Nothing Then
reg = reg.OpenSubKey("ODBC")
If reg IsNot Nothing Then
reg = reg.OpenSubKey("ODBC.INI")
If reg IsNot Nothing Then
For Each dsn As String In reg.GetSubKeyNames
dsnNames.Add(dsn)
Next
End If
End If
End If
For Each Name As String In dsnNames
ComboBox1.Items.Add(Name)
Next Name
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DsnLookup()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim connString As String = "Database='combobox data;Data Source='ip adres odbc;" _
& "User Id=root;Password=' odbc PWD"
You can get the Server Name (or IP) and Database name from the ODBC.INI but it doesn't store the password. Either include a master password in your connectionstring (securely of course) or look into other authentication options.
This is how to get the Database and Server info from the registry. Keeping your code the same, but replacing the Button1.Click event and adding an additional function:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If ComboBox1.SelectedIndex >= 0 Then 'Make sure something from dropdown selected
Dim connString As String = String.Format("Database='{0}';Data Source='{1}';User Id=root;", GetODBCValue(ComboBox1.SelectedItem, "Database"), GetODBCValue(ComboBox1.SelectedItem, "Server"))
End If
End Sub
Private Function GetODBCValue(ByVal ODBCName As String, ByVal ValueName As String) As String
Dim reg As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software")
reg = reg.OpenSubKey("ODBC")
reg = reg.OpenSubKey("ODBC.INI")
reg = reg.OpenSubKey(ODBCName)
Return reg.GetValue(ValueName)
End Function
thank you for the answer
I tried to edit it
Private Function GetODBCValu(ByVal ODBCName As String, ByVal ValueName As String) As String
Dim dsnNames As New List(Of String)
Dim reg As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software")
reg = reg.OpenSubKey("ODBC")
reg = reg.OpenSubKey("ODBC.INI")
reg = reg.OpenSubKey(ODBCName)
Return reg.GetValue(ValueName)
For Each dsn As String In reg.GetSubKeyNames
dsnNames.Add(dsn)
Next
For Each Name As String In dsnNames
ComboBox1.Items.Add(Name)
Next Name
End Function
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim connString As String = String.Format("Database='{0}';Data Source='{1}';User Id=root;", GetODBCValu(ComboBox1.SelectedItem, "Database"), GetODBCValu(ComboBox1.SelectedItem, "Server"))
Dim conn As New MySqlConnection(connString)
Dim cmd As New MySqlCommand()
Try
Call conecDB()
dt = New DataTable 's_table
Dim con As New SqlConnection
DateTimePicker1.CustomFormat = "yyyy-MM-dd"
DateTimePicker1.Format = DateTimePickerFormat.Custom
DateTimePicker2.CustomFormat = "yyyy-MM-dd"
DateTimePicker2.Format = DateTimePickerFormat.Custom
conn.Open()
cmd.Connection = conn
da = New MySql.Data.MySqlClient.MySqlDataAdapter("select --- ", connDB)
comBuilderDB = New MySql.Data.MySqlClient.MySqlCommandBuilder(da)
da.Fill(dt)
dbvypis.DataSource = dt
conn.Close()
MessageBox.Show("COMPLET")
Catch ex As MySqlException
Console.WriteLine("Error: " & ex.ToString())
End Try
Try
'declaring variable as integer to store the value of the total rows in the datagridview
Dim max As Integer = dbvypis.Rows.Count - 1
Dim total As String = "TOTAL ----->"
Dim TOTALCOST As Integer = 0
'getting the values of a specific rows
For Each row As DataGridViewRow In dbvypis.Rows
'formula for adding the values in the rows
TOTALCOST += row.Cells(1).Value
Next
dbvypis.Rows(max).Cells(1).Value += TOTALCOST
dbvypis.Rows(max).Cells(0).Value = total
Catch ex As Exception
MsgBox(ex.Message)
End Try
It occurred to me that if I select a database in the comboboxu so it gets into ODBC and connString to the command adds the server and database name
Then it writes to me in the result Index is out of range, Index must be non-negative and must be smaller than the collection size. Parameter name: index
I am attempting to make a connection to MySQL server, take input from a text box, the use the information to run query and store it in a listbox.
To go even further I would like to and make the listbox update as I type in the text box.
Whenever I run run the vb nothing populates. I even tried changing the query to something basic, select * from securePasswordList.users; And I can't get anything to populate.
Any suggestions or criticism? THanks! Still learning quite a bit about VB...and a long ways to go.
Imports MySql.Data.MySqlClient
Public Class Reveal
Public Property MyDataClass As SecurePasswordList
Dim lastNameInput As String
Dim firstNameInput As String
Dim connStr As String = "server=0.0.0.0;user=johndoe;database=securePasswordList;port=3306;password=password;"
Dim conn As New MySqlConnection(connStr)
Dim SQL As String = "select password from securePasswordList.users where LAST_NAME like ' " & lastNameInput & "%'"
Dim cmd As MySqlCommand = New MySqlCommand(SQL, conn)
Private Sub Reveal_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub firstName_TextChanged(sender As Object, e As EventArgs) Handles lastNameTextBox.TextChanged
lastNameInput = lastNameTextBox.Text
listBox.Items.Add(cmd)
End Sub
Private Sub lastName_TextChanged(sender As Object, e As EventArgs) Handles firstNameTextBox.TextChanged
firstNameInput = firstNameTextBox.Text
End Sub
Private Sub listBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles listBox.SelectedIndexChanged
End Sub
End Class
One of your issues is that you are not actually executing the MySqlCommand anywhere. Also, I would like to point you to this link, since you have a potential security issue in your current code in the way you build your select-string.
Here is an example of how you could retrieve a password:
Private Function RetrievePassword(ByVal lastName As String) As String
Using conn As New MySqlConnection(connStr)
Using comm As New MySqlCommand(query, conn)
comm.Parameters.AddWithValue("#LastName", lastName & "%'")
Dim result As Object = comm.ExecuteScalar()
If result Is Nothing Then
handle as you like...
End If
Return result.ToString
End Using
End Using
End Function
query would contain a placeholder for the parameter like so:
Private Const query As String =
"select password from securePasswordList.users where LAST_NAME like #LastName"
I want to import a class to another class so that I don't have to write the same code X times.
I have a file with the connection to the database called connectDB.vb.
Imports MySql.Data.MySqlClient
Namespace connectDB1
Public Class connectDB
Dim connection As New MySqlConnection("Server=localhost; UserId=root;
Password=root; Database=something")
Public Sub doConnection()
Try
connection.Open()
Catch ex As Exception
MsgBox("Error")
End Try
End Sub
End Class
End Namespace
And I want to import connectDB.vb to File1.vb
Imports MySql.Data.MySqlClient
Imports MyApp.connectDB1
Public Class File1
Dim connectDataBase As New connectDB
Dim connection As New MySqlConnection("Server=localhost; UserId=root; Password=root; Database=something")
Private Sub File1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'doConnection()
connectDataBase.doConnexion()
End Sub
'Private Sub doConnection()
' Try
' connection.Open()
' Catch ex As Exception
' MsgBox("Error")
' End Try
'End Sub
Private Sub addProduct()
Dim dbcomm As MySqlCommand
Dim dbread As MySqlDataReader
If txtBoxQuantity.Text <> "" And txtBoxPrice.Text <> "" And txtBoxProduct.Text <> "" Then
dbcomm = New MySqlCommand("insert into products (price, stock, name) values(#price, #stock, #name)", connection)
dbcomm.Parameters.AddWithValue("#price", txtBoxPrice.Text())
dbcomm.Parameters.AddWithValue("#stock", txtBoxQuantity.Text())
dbcomm.Parameters.AddWithValue("#name", txtBoxProduct.Text())
dbread = dbcomm.ExecuteReader() ' GIVES ERROR
dbread.Close()
End If
End Sub
Private Sub add_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles agregarProducto.Click
addProduct()
End Sub
End Class
But when I run this code that it's suposed to save the data in the DB it gives me this error:
InvalidOperationException was unhandled. Connection must be valid and open.
connectDB.vb connects to the database since I debugged and it connects to the DB, but when I want to do some sql sentence in the File1.vb it gives that error.
Without trying to import the class the code works, but I'm just trying to improve my code, as you can see the commented code is the code I used to connect to the database.
Try adding this
Public Sub New()
connectDataBase = New connectDB()
connection = New MySqlConnection("Server=localhost; UserId=root; Password=root; Database=something")
End Sub
I have a problem with access to my datebase MySQL after closing it. I use Windows Form and MySql Connector from MySql official website to connect to datebase. I use MySQL in XAMPP.
If I open my connection I can do a simple query. But when I close a connection I can still do this query. Why?
Here is my code:
Imports MySql.Data.MySqlClient
Public Class Form1
Dim polaczenieMySql As New MySqlConnection
Dim mySQL As PolaczenieMySQL
Public Sub New()
InitializeComponent()
mySQL = New PolaczenieMySQL(Me)
End Sub
Private Sub btnPolaczMySQL_Click(sender As Object, e As EventArgs) Handles btnPolaczMySQL.Click
mySQL.Polacz()
End Sub
Private Sub RozlaczMySQL_Click(sender As Object, e As EventArgs) Handles btnRozlaczMySQL.Click
mySQL.Rozlacz()
End Sub
Private Sub btnZapytanie_Click(sender As Object, e As EventArgs) Handles btnZapytanieMySQL.Click
Dim zapytanie As String = "SELECT title, price, book_id from books"
mySQL.WykonajZapytanie(zapytanie)
End Sub
End Class
And my connection class:
Imports MySql.Data.MySqlClient
Public Class PolaczenieMySQL
Dim polaczenie As MySqlConnection = New MySqlConnection()
Dim glowneOkno As Form1
Public Sub New(form As Form1)
glowneOkno = form
End Sub
Public Sub Polacz()
polaczenie.ConnectionString = ("server=localhost;user id=root;password=;database=test")
Try
polaczenie.Open()
MessageBox.Show("Połączono z bazą danych MySQL.")
glowneOkno.labelPolaczenieMySQL.Text = "Połączono"
glowneOkno.labelPolaczenieMySQL.ForeColor = Color.Green
Catch myerror As MySqlException
MessageBox.Show("Nie udało się połączyć z bazą danych MySQL: " & myerror.Message)
End Try
End Sub
Public Sub Rozlacz()
Try
polaczenie.Close()
MessageBox.Show("Rozłączono z bazy danych MySQL.")
glowneOkno.labelPolaczenieMySQL.Text = "Nie połączono"
glowneOkno.labelPolaczenieMySQL.ForeColor = Color.Red
Catch myerror As MySqlException
MessageBox.Show("Błąd rozłączenia z bazy danych MySQL: " & myerror.Message)
Finally
polaczenie.Dispose()
End Try
End Sub
Public Sub WykonajZapytanie(ByVal zapytanie As String)
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
Try
Dim komenda As MySqlCommand = New MySqlCommand(zapytanie, polaczenie)
SDA.SelectCommand = komenda
SDA.Fill(dbDataSet)
bSource.DataSource = dbDataSet
glowneOkno.DataGridViewMySQL.DataSource = bSource
SDA.Update(dbDataSet)
Catch ex As MySqlException
MessageBox.Show("Nie jesteś połączony z bazą")
End Try
End Sub
End Class
As I said before, after closing connection (mySQL.Rozlacz()) I can still do a query (mySQL.WykonajZapytanie(zapytanie)). What is wrong with this?
PS. Sorry for my polish names
If you look at the docs about the DbDataAdapter you could read this remark
The Fill method retrieves the data from the data source using a SELECT
statement. The IDbConnection object associated with the select command
must be valid, but it does not need to be open. If the IDbConnection
is closed before Fill is called, it is opened to retrieve data and
then closed. If the connection is open before Fill is called, it
remains open.
The MySqlDataAdapter inherits from the DbDataAdapter and there is no override of the Fill method, so it is the inherited class (DbDataAdapter) that works with the associated command, reopening the closed connection and then closing it.
EDIT
You asked also how to avoid this behavior, well you could add a boolean property to your class PolaczenieMySQL that maintains the state of your MySqlConnection
Private _isDead As Boolean
Public Property IsDead() As Boolean
Get
Return _isDead
End Get
Private Set(ByVal value As String)
_isDead = value
End Set
End Property
Now you could set this property to False when you open the connection and True when you close it.
Then check its value before executing the WykonajZapytanie sub
Public Sub WykonajZapytanie(ByVal zapytanie As String)
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
if Me.IsDead Then
Throw new Exception("Invalid usage of this class")
End If
......
End Sub
Notice that there is a simpler check using the MySqlConnection property State
if polaczenie.State <> ConnectionState.Open Then
......
but, given the fact that in your Rozlacz method you dispose the connection I suggest to implement the first workaround.
Finally, I really think that you should change the whole pattern of usage. The connection should be opened, used and closed in the same method where it is required. Your actual infrastructure render this impossible. It is better to get rid of the Polacz and Rozlacz and use the mentioned pattern without the need of a global variable for the connection.
In this prgram i am getting below error:
The DataSourceID of GridView1 must be the ID of a control of type IDataSource. A control with ID SqlDataSource1 could not be found.
Imports MySql.Data.MySqlClient
Imports System.Data
Partial Class _Default
Inherits System.Web.UI.Page
Dim con As MySqlConnection = New MySqlConnection("data source=localhost;database=dbconnect;user id=root;password=search;")
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub btn_display_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btn_display.Click
Dim connection As MySqlConnection = New MySqlConnection("data source=localhost;database=dbconnect;user id=root;password=search;")
Dim mydataset As New DataSet()
Dim mydataadpter As MySqlDataAdapter = New MySqlDataAdapter()
Dim mysql As MySqlCommand = New MySqlCommand("select * from userinfo", connection)
connection.Open()
mydataadpter.SelectCommand = mysql
mydataadpter.Fill(mydataset, "product")
Try
'GridView1.DataSource = mydataset
GridView1.DataBind()
GridView1.DataMember = "product"
connection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Remove the DataSourceID attribute and its value (DataSourceID="SqlDataSource1") from your GridView1 control inside the source view (.aspx).
The problem is that the DataSourceID property is designed to be used in an ASPX page and you are in the code. You want to use the DataSource property instead. It is looking in your ASPX page for a control named "SqlDataSource1" and there is not one. If you create this SqlDataSource1 object in the ASPX page instead of in the code you will be able to set the DataSourceID to the ID of the SqlDataSource1 object
DataSourceID="SqlDataSource1"