Populating a Menu from a Database - sql

I found some very useful code on populating a menu from a database and customised it a bit but I am struggling to create a third level to menu as in the below example(2.1.1 and 2.1.2)
Home
About Us
2.1 Management Team
2.1.1 Team Member 1
2.1.2 Team Member 2
2.2 Company Information
Contact Us
I have listed my code below.
Imports System.IO
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Imports iconCloud_BL
Partial Class Main
Inherits System.Web.UI.MasterPage
Public Params As New List(Of SqlParameter)
Dim clsDatabase As New clsDatabaseLogic
Protected Sub Page_Load(sender As Object, e As EventArgs)
If Not Me.IsPostBack Then
Dim dt As DataTable = Me.GetData(0, 2)
PopulateMenu(dt, 0, Nothing)
End If
End Sub
Private Function GetData(parentMenuId As Integer, role As Integer) As DataTable
Dim query As String = "SELECT [menusMenuId], [menusTitle], [menusDescription], [menusUrl] FROM [configMenus] WHERE menusParentMenuId = #ParentMenuId AND menusRole = #Role"
Dim constr As String = ConfigurationManager.ConnectionStrings("iconDataConnections").ConnectionString
Using con As New SqlConnection(constr)
Dim dt As New DataTable()
Using cmd As New SqlCommand(query)
Using sda As New SqlDataAdapter()
cmd.Parameters.AddWithValue("#ParentMenuId", parentMenuId)
cmd.Parameters.AddWithValue("#Role", role)
cmd.CommandType = CommandType.Text
cmd.Connection = con
sda.SelectCommand = cmd
sda.Fill(dt)
End Using
End Using
Return dt
End Using
End Function
Private Sub PopulateMenu(dt As DataTable, parentMenuId As Integer, parentMenuItem As MenuItem)
Dim dtChild As DataTable
Dim currentPage As String = Path.GetFileName(Request.Url.AbsolutePath)
For Each row As DataRow In dt.Rows
Dim rowcount = getMaxRows()
Dim menuItem As New MenuItem() With {
.Value = row("menusMenuId").ToString(),
.Text = row("menusTitle").ToString(),
.NavigateUrl = row("menusUrl").ToString(),
.Selected = row("menusUrl").ToString().EndsWith(currentPage, StringComparison.CurrentCultureIgnoreCase)
}
If parentMenuId = 0 Then
mainMenu.Items.Add(menuItem)
dtChild = Me.GetData(Integer.Parse(menuItem.Value), 2)
PopulateMenu(dtChild, Integer.Parse(menuItem.Value), menuItem)
ElseIf parentMenuId > 0 Then
For i As Integer = 0 To rowcount
mainMenu.Items.Add(menuItem)
dtChild = Me.GetData(Integer.Parse(i), 2)
PopulateMenu(dtChild, Integer.Parse(i), menuItem)
Next
Else
parentMenuItem.ChildItems.Add(menuItem)
End If
Next
End Sub
Public Function getMaxRows()
clsDatabase.SQLCmd.CommandText = "sp_iconCloud_configMenuRowsCount"
clsDatabase.SQLCmd.CommandType = CommandType.StoredProcedure
clsDatabase.SQLCmd.Connection = clsDatabase.SQLConn
clsDatabase.SQLConn.Open()
Dim count As Integer = clsDatabase.SQLCmd.ExecuteScalar()
clsDatabase.SQLConn.Close()
clsDatabase.SQLCmd.Parameters.Clear()
Return count
End Function
End Class

Related

FlowLayoutPanel Update & Delete Records in Database

Can someone tell me how i can manage Delete Record & Update Record from FlowLayoutPanel
So i have 1 user control :
then fetch the db:
Public Function FindTasksUser() As DataTable
Using cons As New SQLiteConnection(ServerStatus)
Using cmd As New SQLiteCommand()
cmd.Connection = cons
cmd.CommandText = "SELECT * FROM Tasks WHERE accountName = #GetUser ORDER BY [ID] ASC;"
cmd.Parameters.AddWithValue("#GetUser", UserUserAcc).ToString()
cons.Open()
Using sda As New SQLiteDataAdapter(cmd)
Dim dt As New DataTable()
sda.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
then call the function in maincp form
Private Sub GenerateTasksUser()
FlowLayoutPanel3.Controls.Clear()
Dim dt As DataTable = New ClassBLL().GetTasksUser()
If dt IsNot Nothing Then
If dt.Rows.Count > 0 Then
Dim listItems As UserTasks() = New UserTasks(dt.Rows.Count - 1) {}
For i As Integer = 0 To 1 - 1
For Each row As DataRow In dt.Rows
Dim listItem As New UserTasks()
listItems(i) = listItem
listItems(i).TaskTitle = row("taskstitle").ToString()
listItems(i).TaskSubject = row("tasksubject").ToString()
listItems(i).TaskFrom = row("taskfromname").ToString()
FlowLayoutPanel3.Controls.Add(listItems(i))
Next
Next
End If
End If
End Sub
I have try inside user control img button this options, seems to delete the row, but im not sure is it the right one and how to delete from database
Private Sub Guna2ImageButton1_Click(sender As Object, e As EventArgs) Handles Guna2ImageButton1.Click
MainCP.FlowLayoutPanel3.Controls.RemoveByKey(Me.Name)
'or Directly to use Dispose
Dispose()
'or another option
Parent.Controls.Remove(Me)
'or another option i think is:
For Each control As Control In MainCP.FlowLayoutPanel3.Controls
MainCP.FlowLayoutPanel3.Controls.Remove(control)
control.Dispose()
Next
End Sub
And how to update in database when i click Checbox1 and button 2 to save the records in database in column "Status" with text "Done"
Most of the verbage to go with this code is provided in my comments. This has not been tested. Sqlite is an anethma to me. I gasp at the "flexable" typing.
The actual update code takes a list of the IDs from the original DataTable. You add the parameter once to the parameters collection and then loop through the values to update.
Public Class ClassBLL
Private ServerStatus As String = "Your connection string"
Public Sub UpdateRecords(lst As List(Of Integer))
Dim sql = "Update Tasks Set Status = 'Done' Where ID = #ID"
Using cn As New SQLiteConnection(ServerStatus),
cmd As New SQLiteCommand(sql, cn)
cmd.Parameters.Add("#ID", DbType.Int32)
cn.Open()
For Each i In lst
cmd.Parameters("#ID").Value = i
cmd.ExecuteNonQuery()
Next
End Using
End Sub
Public Function FindTasksUser(UserUserAcc As String) As DataTable
Dim dt As New DataTable()
Dim sql = "SELECT * FROM Tasks WHERE accountName = #GetUser ORDER BY [ID] ASC;"
Using cons As New SQLiteConnection(ServerStatus)
Using cmd As New SQLiteCommand(sql, cons)
cmd.Parameters.AddWithValue("#GetUser", UserUserAcc)
cons.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
End Using
Return dt
End Function
End Class
Private Class MainCP
Private UserAccount As String
Private Sub GenerateTasksUser()
FlowLayoutPanel3.Controls.Clear()
Dim dt As DataTable = New ClassBLL().FindTasksUser(UserAccount)
If dt IsNot Nothing Then
If dt.Rows.Count > 0 Then
Dim listItems As New List(Of UserTasks)
For Each row As DataRow In dt.Rows
Dim listItem As New UserTasks()
listItem.TaskTitle = row("taskstitle").ToString()
listItem.TaskSubject = row("tasksubject").ToString()
listItem.TaskFrom = row("taskfromname").ToString()
listItems.Add(listItem)
Next
FlowLayoutPanel3.Controls.AddRange(listItems.ToArray)
End If
End If
Dim IDList = (From row As DataRow In dt.AsEnumerable
Select CInt(row("ID"))).ToList
SomeOtherForm.ListOfIDs = IDList
End Sub
End Class
Public Class SomeOtherForm
Public Shared ListOfIDs As List(Of Integer)
Private Sub Guna2ImageButton1_Click(sender As Object, e As EventArgs) Handles Guna2ImageButton1.Click
'I don't think Me is referring to what you think it is.
For Each control As Control In MainCP.FlowLayoutPanel3.Controls
MainCP.FlowLayoutPanel3.Controls.Remove(control)
control.Dispose()
'You also need to get rid of any handlers you have added.
Next
Dim bll As New ClassBLL
bll.UpdateRecords(ListOfIDs)
End Sub
End Class
Public Class UserTasks
Inherits UserControl
Public Property TaskTitle As String
Public Property TaskSubject As String
Public Property TaskFrom As String
End Class

Having issues when 2 users are working with the same program

Public Class DataAccess
Dim dataAcc As New DataAccess
Public Shared dtx As New DataTable
Private Shared ConStr As String = "Server = 10.18.206.30;database=PeajeFacturacion;User ID=FacturacionUsr;Password = ukShLq?U6&hNxDxN+67!XaYq"
Public Shared Function AddOneRecord(PK As String) As DataTable
Using cn As New SqlConnection(ConStr),
cmd As New SqlCommand("Select c.idCruce, c.FechaCruce, c.HoraCruce, c.claseVehiculo, c.Importe,
c.codigoCobro, n.nomCaseta
from dbo.Cruce AS c
JOIN dbo.nombre_caseta AS n
ON n.numCaseta=c.ClavePlaza
where c.CodigoCobro = #PK;", cn)
cmd.Parameters.Add("#PK", SqlDbType.VarChar).Value = PK
cn.Open()
dtx.Load(cmd.ExecuteReader)
End Using
Return dtx
End Function
End Class
I use that part to create the connection just like the example #Mary posted. Then:
Protected Sub btnAgregar_Click(sender As Object, e As EventArgs) Handles btnAgregar.ServerClick
Dim numTicket As String = txtNoTicket.Text
Dim dtx As New DataTable
Dim pk As String
pk = txtNoTicket.Text
Dim con2 As New SqlConnection
Dim cmd2 As New SqlCommand
Dim dr As SqlDataReader
Dim dtx2 As DataTable
Dim status As Boolean = False
'If Not Integer.TryParse(ticket.Text, pk) Then
If String.IsNullOrEmpty(pk) Then
'ScriptManager.RegisterStartupScript(Me, Page.GetType, "Script", "showDisplay();", True)
cFunciones.mostrarDivAlertaAA("Type a number", "dangerNormal", Me.Page, "")
Else
dtx = DataAccess.AddOneRecord(pk)
So when adding tickets the issue is the ticket 1 user adds, gets added to the other user even though they use different sessions and different computers. The program is in test fase right now.
You can get rid of Shared in the DatAccess class. Then each instance of the class will have its own data. Now you must declare an instance of the class and call the method on that instance.
Public Class DataAccess
Dim dataAcc As New DataAccess
Public dtx As New DataTable
Private ConStr As String = "Server = 10.18.206.30;database=PeajeFacturacion;User ID=FacturacionUsr;Password = ukShLq?U6&hNxDxN+67!XaYq"
Public Function AddOneRecord(PK As String) As DataTable
Using cn As New SqlConnection(ConStr),
cmd As New SqlCommand("Select c.idCruce, c.FechaCruce, c.HoraCruce, c.claseVehiculo, c.Importe,
c.codigoCobro, n.nomCaseta
from dbo.Cruce AS c
JOIN dbo.nombre_caseta AS n
ON n.numCaseta=c.ClavePlaza
where c.CodigoCobro = #PK;", cn)
cmd.Parameters.Add("#PK", SqlDbType.VarChar).Value = PK
cn.Open()
dtx.Load(cmd.ExecuteReader)
End Using
Return dtx
End Function
End Class
Protected Sub btnAgregar_Click(sender As Object, e As EventArgs) Handles btnAgregar.ServerClick
Dim dtx As New DataTable
Dim pk = txtNoTicket.Text
If String.IsNullOrEmpty(pk) Then
cFunciones.mostrarDivAlertaAA("Type a number", "dangerNormal", Me.Page, "")
Else
Dim datAcc As New DataAccess
dtx = datAcc.AddOneRecord(pk)
End If
End Sub

Import very large .csv to List array, then copy to DataTable

I am trying to import a large CSV file, where I am dumping each row of the input csv file into an array (vector), which is NumColumns long. I fetched some code to copy a list to a DataTable, however, I am not sure the IList (IsEnumerable?) is needed. I also haven't looked into what T is.
My gut feeling is that I can go to some other code I have to load a DataTable with row and column data from a 2-dimensional array x(,), but for some reason I think there may be a fast way to simply .add(x), i.e. add the entire row vector to the DataTable to keep the speed up. You don't want to loop through columns(?)
Below is the code which will open up any .csv.
Imports System.ComponentModel
Imports System.IO
Public Class Form1
Dim NumColumns As Integer
Dim ColumnNames() As String
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim filename As String = Nothing
With OpenFileDialog1
.FileName = "*.csv"
.CheckFileExists = True
.ShowReadOnly = True
.Filter = "Comma delimited *.csv|*.csv"
If .ShowDialog = DialogResult.OK Then
filename = .FileName
End If
End With
Dim csvreader As New StreamReader(filename)
Dim inputLine As String = ""
inputLine = csvreader.ReadLine()
Dim buff() As String = Split(inputLine, ",")
NumColumns = UBound(buff)
ReDim ColumnNames(UBound(buff) + 1)
For j As Integer = 0 To NumColumns
ColumnNames(j + 1) = buff(j)
Next
inputLine = csvreader.ReadLine()
Do While inputLine IsNot Nothing
Dim rowdata = New MyDataArray(NumColumns)
Dim csvArray() As String = Split(inputLine, ",")
For i As Integer = 0 To NumColumns
rowdata.x(i) = csvArray(i)
Next
MyDataArray.DataArray.Add(rowdata)
inputLine = csvreader.ReadLine()
Loop
Dim dgv As New DataGridView
dgv.DataSource = ToDataTable(MyDataArray.DataArray)
dgv.Width = 1000
dgv.Height = 1000
Me.Controls.Add(dgv)
End Sub
Public Shared Function ToDataTable(Of T)(data As IList(Of T)) As DataTable
Dim properties As PropertyDescriptorCollection = TypeDescriptor.GetProperties(GetType(T))
Dim dt As New DataTable()
For i As Integer = 0 To properties.Count - 1
Dim [property] As PropertyDescriptor = properties(i)
dt.Columns.Add([property].Name, [property].PropertyType)
Next
Dim values As Object() = New Object(properties.Count - 1) {}
For Each item As T In data
For i As Integer = 0 To values.Length - 1
values(i) = properties(i).GetValue(item)
Next
dt.Rows.Add(values(1))
Next
Return dt
End Function
End Class
Public Class MyDataArray
Public Shared DataArray As New List(Of MyDataArray)()
Public Property x() As Object
Sub New(ByVal cols As Integer)
ReDim x(cols)
End Sub
End Class
Maybe this code will help?
You can use OleDB to convert the CSV to a Database and then put it into a datatable. All you need is a DataGridView and form (If you want to print it). Then you can use teh code below to accomplish what you need to do.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim file As String = "test.txt"
Dim path As String = "C:\Test\"
Dim ds As New DataSet
Try
If IO.File.Exists(IO.Path.Combine(path, file)) Then
Dim ConStr As String = _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _
path & ";Extended Properties=""Text;HDR=No;FMT=Delimited\"""
Dim conn As New OleDb.OleDbConnection(ConStr)
Dim da As New OleDb.OleDbDataAdapter("Select * from " & _
file, conn)
da.Fill(ds, "TextFile")
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
DataGridView1.DataSource = ds.Tables(0)
End Sub
End Class
However, you could always convert it to an xml and work from there
Imports System.IO
Module Module3
Public Function _simpleCSV2tbl(CSVfile As String) As DataTable
Dim watch As Stopwatch = Stopwatch.StartNew()
watch.Start()
'A,B,C,D,E
'00001,4,1,2,3560
'00002,4,12,1,2000
'00003,1,4,2,4500
'00004,4,12,1,2538.63
'00005,1,1,2,3400
'00006,2,5,2,2996.48
Dim dTable As New DataTable(CSVfile)
Using reader As New StreamReader(CSVfile)
Dim CSV1stLine As String = reader.ReadLine
Dim getCols = (From s In CSV1stLine.Split(",") Select s).ToList()
Dim setTblColumns = (From c In getCols Select dTable.Columns.Add(c, GetType(String))).ToList
Dim ReadToEnd As String = reader.ReadToEnd()
Dim getRows = (From s In ReadToEnd.Split(vbLf) Select s).ToArray
_setTblRows(getRows, dTable)
Console.WriteLine(String.Format("Elapsed: {0}", Format(watch.Elapsed.TotalMilliseconds, "F"), dTable.Rows.Count))
reader.Close()
reader.Dispose()
End Using
_ShowTbl(dTable, 10)
End Function
Public Function _setTblRows(getRows As String(), dTable As DataTable) As IEnumerable
_setTblRows = getRows.Select(Function(r) dTable.LoadDataRow(r.Split(","), False)).ToArray()
End Function
Public Sub _ShowTbl(ByVal dTable As DataTable, Optional ByVal rPad As Short = 0)
If dTable.TableName = Nothing Then dTable.TableName = "NoName"
If rPad = 0 Then
Console.WriteLine(String.Format("->Unformatted Table: {0}, Count={1}", dTable.TableName, dTable.Rows.Count))
Else
Console.WriteLine(String.Format("->Formatted Table: {0}, Count={1}", dTable.TableName, dTable.Rows.Count))
End If
_ShowTblColumns(dTable.Columns, rPad)
_ShowTblRows(dTable.Rows, rPad)
End Sub
Public Function _ShowTblColumns(ByVal TblColumns As DataColumnCollection, Optional ByVal rPad As Short = 0)
Dim getTblColumns = (From c As DataColumn In TblColumns Select c.ColumnName).ToList()
Console.WriteLine(String.Join(",", getTblColumns.Select(Function(s) String.Format(s.PadLeft(rPad, vbNullChar)).ToString).ToArray))
End Function
Public Function _ShowTblRow(ByVal Row As DataRow, Optional ByVal rPad As Short = 0)
Dim getRowFields = (From r In Row.ItemArray Select r).ToList
Console.WriteLine(String.Join(",", getRowFields.Select(Function(s) String.Format(s.PadLeft(rPad, vbNullChar)).ToString).ToArray))
End Function
Public Function _ShowTblRows(ByVal Rows As DataRowCollection, Optional ByVal rPad As Short = 0)
Dim rCount As Integer
For Each row As DataRow In Rows
_ShowTblRow(row, rPad)
rCount += 1
If rCount Mod 20 = 0 Then
If NewEscape(String.Format(" {0} out of {1}", rCount.ToString, (Rows.Count).ToString)) Then Exit Function
End If
Next row
Console.WriteLine()
End Function
Public Function _NewEscape(ByVal Message As String) As Boolean
Console.Write("{0} / Press any key to continue or Esc to quit {1}", Message, vbCrLf)
Dim rChar As Char = Console.ReadKey(True).KeyChar
Dim rEscape As Boolean
If rChar = Chr(27) Then rEscape = True
Return rEscape
End Function
End Module

Why I am getting System.Data.DataRowViewā€¯ instead of real values from my Listbox in vb.net

Could someone help here?
I need to extract data from a Database into a combolistbox in VB.net. I have got the data, but now find that The first and the 'x' line need to be removed from the combolistbox (they are validation entries for another software) and shouldn't be selected for this application.
I tried to simply remove the offending entries from lists by using :- cbCubeARivet.Items.RemoveAt(index), but had an error letting me know I cannot use "Items" with a DataSource.
I decided to send the data to a listbox, and then try to transfer the entries to the combolistbox. This then lead me to getting multiple entries of System.Data.DataRowView in the combolist box. To demonstrate my problem I include an example code modified from MSDN.
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Collections
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Populate the list box using an array as DataSource.
Dim SQLConnectionString As String = "Data Source=HL605\RIVWARE;Database=RIVWARE;Integrated Security=true;"
Dim mySQLConnection As New SqlConnection(SQLConnectionString)
mySQLConnection.Open()
Dim SQLDataTable As New System.Data.DataTable
'Create new DataAdapter
'Use DataAdapter to fill DataTable
Dim mySQLDataAdapter = New SqlDataAdapter("SELECT * FROM [Rivware].[dbo].[RivetTypes]", mySQLConnection)
mySQLDataAdapter.Fill(SQLDataTable)
ListBox1.DataSource = SQLDataTable
ListBox1.DisplayMember = "RivetType"
'original code from MSDN
'Dim USStates As New ArrayList()
'USStates.Add(New USState("Alabama", "AL"))
'USStates.Add(New USState("Washington", "WA"))
'USStates.Add(New USState("West Virginia", "WV"))
'USStates.Add(New USState("Wisconsin", "WI"))
'USStates.Add(New USState("Wyoming", "WY"))
'ListBox1.DataSource = USStates
' Set the long name as the property to be displayed and the short
' name as the value to be returned when a row is selected. Here
' these are properties; if we were binding to a database table or
' query these could be column names.
' Bind the SelectedValueChanged event to our handler for it.
AddHandler ListBox1.SelectedValueChanged, AddressOf ListBox1_SelectedValueChanged
' Ensure the form opens with no rows selected.
ListBox1.ClearSelected()
End Sub 'NewNew
Private Sub ListBox1_SelectedValueChanged(ByVal sender As Object, ByVal e As EventArgs)
If ListBox1.SelectedIndex <> -1 Then
TextBox1.Text = ListBox1.SelectedValue.ToString()
' If we also wanted to get the displayed text we could use
' the SelectedItem item property:
' Dim s = CType(ListBox1.SelectedItem, USState).LongName
End If
End Sub
End Class 'ListBoxSample3
Public Class USState
Private myShortName As String
Private myLongName As String
Public Sub New(ByVal strLongName As String, ByVal strShortName As String)
Me.myShortName = strShortName
Me.myLongName = strLongName
End Sub 'NewNew
Public ReadOnly Property ShortName() As String
Get
Return myShortName
End Get
End Property
Public ReadOnly Property LongName() As String
Get
Return myLongName
End Get
End Property
End Class 'USState
I may not get this correct so here goes, the following uses mocked up data to display a string in both a ListBox and ComboBox where a integer is available by casting the current item as a DataRowView, access Row then access the data via Row.Field(Of Integer)("ID").
In the code I use a copy of the underlying DataTable for the ComboBox as using the same data table for listbox and combobox will cause one to traverse when is generally unwanted. The cast aspect would be done in another event but wanted to stay simple. Again I may not be on track here, let me know and can adjust to better suit your question.
Code using Option Infer On for the Linq anonymous statement which could be strongly typed too.
Dim dt As New DataTable
dt.Columns.Add(New DataColumn With {.ColumnName = "ID", .DataType = GetType(Integer)})
dt.Columns.Add(New DataColumn With {.ColumnName = "Name", .DataType = GetType(String)})
Dim data =
(
From M In System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.MonthNames
Where Not String.IsNullOrEmpty(M)).ToList.Select(
Function(monthName, index) New With
{
.ID = index, .Name = monthName
}
).ToList
For Each item In data
dt.Rows.Add(New Object() {item.ID, item.Name})
Next
ListBox1.DataSource = dt
ListBox1.DisplayMember = "Name"
ComboBox1.DataSource = dt.Copy
ComboBox1.DisplayMember = "Name"
Dim theTable As DataTable = CType(ComboBox1.DataSource, DataTable)
Dim theRow As DataRow = theTable.AsEnumerable _
.Where(
Function(row) row.Field(Of String)("Name") = "September") _
.FirstOrDefault()
If theRow IsNot Nothing Then
theTable.Rows.Remove(theRow)
End If
Thanks again #Karen Payne,
I used your code to lead me in the right direction.
I created a new application and added a textbox, and two Listboxes, then paste the code. To run you will need to point to your own Server, Database, and Table.
This is what I came up with. It is useful as this will give you the actual data in a useable form:-
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Collections
Imports System.Data.SqlClient
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' get the data
Dim SQLConnectionString As String = "Data Source=HL605\RIVWARE;Database=RIVWARE;Integrated Security=true;"
Dim mySQLConnection As New SqlConnection(SQLConnectionString)
' Populate the list box using an array as DataSource.
mySQLConnection.Open()
Dim SQLDataTable As New System.Data.DataTable
'Create new DataAdapter
Dim mySQLDataAdapter = New SqlDataAdapter("SELECT * FROM [Rivware].[dbo].[RivetTypes]", mySQLConnection)
mySQLDataAdapter.Fill(SQLDataTable)
ListBox1.DataSource = SQLDataTable
ListBox1.DisplayMember = "RivetType"
' remove validation data from list
Dim Count As Integer
Dim X As Integer
'get the column of data to search for
For Count = 0 To ListBox1.DataSource.Columns.Count - 1
X = InStr(ListBox1.DataSource.Columns.Item(Count).ToString, "Name")
If X <> 0 Then Exit For
Next
' now search for any invalid rows, in that column. those containing "---"
Dim TheTable As DataTable = CType(ListBox1.DataSource, DataTable)
Dim theRow As DataRow() = TheTable.Select()
Dim RowNumber As Integer
For RowNumber = 0 To UBound(theRow) - 1
If theRow(RowNumber).Item(Count).ToString <> "---" Then
' data is OK so transer it to the other listbox
ListBox2.Items.Add(theRow(RowNumber).Item(Count - 1).ToString)
End If
Next
ListBox2.ClearSelected()
End Sub 'NewNew
Private Sub ListBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox2.SelectedIndexChanged
TextBox1.Text = ListBox2.SelectedItem.ToString()
End Sub
End Class 'ListBoxSample3

Insert data into database by linking class to btnRegister

I am new for programming and trying to learn VB.net through youtube tutorials.
I created a windows form app for users to create new account.
I am also trying to apply the hash and salt technique to store the password for security reason.
The main issue I have is maintaining successful connection between a two class I called "DatabaseManager" and "DataHandling", codes in "btnRegister" and the database called "Test".
The program runs fine. When I click btnRegister after filling the "txtUsername.Text" and "txtPassword.Text", it gives me error that says "ColumnUser_IDdoes not allow nulls.".
So this is where I keep getting issues. I tried to make it work a lot and I have no idea why it is not recording the new data. Here are my codes. I use V Studio 2012. Please help.
Just to be clear I copied some of the codes from internet and tried to make them work with the class
Imports System
Imports System.IO
Imports System.Text
Imports System.Data.OleDb
Imports System.Data
Imports System.Windows.Forms
Imports System.Data.SqlClient
Imports System.Security.Cryptography
Public Class DatabaseManager
Private Const CONNECTION_STRING As String = "Data Source=(localdb)\Projects;Initial Catalog=Test;Integrated Security=True"
Private connection As SqlConnection = Nothing
Private usersdataadapter As SqlDataAdapter = Nothing
Sub New()
connection = New SqlConnection(CONNECTION_STRING)
usersdataadapter = New SqlDataAdapter("select * from Test", connection)
End Sub
Public Sub Register(ByVal Username As String, ByVal Password As String)
connection.Open()
Dim usersDataset As New DataSet()
usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
Dim table As DataTable = usersDataset.Tables("Test")
Dim newRecord As DataRow = table.NewRow()
newRecord("Username") = Username
newRecord("Password") = Password
table.Rows.Add(newRecord)
Dim command As New SqlCommandBuilder(usersdataadapter)
usersdataadapter.Update(usersDataset, "Test")
usersDataset.Dispose()
connection.Close()
End Sub
Public Function UsernameAvailable(ByVal username As String) As Boolean
Dim usersDataset As New DataSet()
usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
usersdataadapter.Fill(usersDataset, "Test")
Dim table As DataTable = usersDataset.Tables("Test")
For i As Integer = 0 To table.Rows.Count - 1
Dim currnetUser As String = table.Rows(i)("Username").ToString().Trim()
If (currnetUser = username) Then
usersDataset.Dispose()
connection.Close()
Return False
End If
Next
Return True
usersDataset.Dispose()
connection.Close()
End Function
Public Function Login(ByVal username As String, ByVal password As String) As Boolean
Dim usersDataset As New DataSet()
usersdataadapter.FillSchema(usersDataset, SchemaType.Source, "Test")
usersdataadapter.Fill(usersDataset, "Test")
Dim table As DataTable = usersDataset.Tables("Test")
For i As Integer = 0 To table.Rows.Count - 1
Dim currnetUser As String = table.Rows(i)("Username").ToString().Trim()
Dim currnetPassword As String = table.Rows(i)("Password").ToString().Trim()
If (currnetUser = username AndAlso currnetPassword = password) Then
usersDataset.Dispose()
connection.Close()
Return True
End If
Next
usersDataset.Dispose()
connection.Close()
Return False
End Function
End Class
Imports System
Imports System.Text
Imports System.Data.OleDb
Imports System.Data
Imports System.Data.SqlClient
Imports System.Windows.Forms
Imports System.Security.Cryptography
Public Class DataHandling
Inherits Form1
Public Shared Function GenerateRandomString() As String
Dim i_key As Integer
Dim Random1 As Single
Dim arrIndex As Int16
Dim sb As New StringBuilder
Dim RandomLetter As String
Dim KeyLetters As String = "abcdefghijklmnopqrstuvwxyz"
Dim KeyNumbers As String = "0123456789"
Dim KeyLength As Integer = 12
Dim LettersArray = KeyLetters.ToCharArray
Dim NumbersArray = KeyNumbers.ToCharArray
For i_key = 1 To KeyLength
Randomize()
Random1 = Rnd()
arrIndex = -1
If (CType(Random1 * 111, Integer)) Mod 2 = 0 Then
Do While arrIndex < 0
arrIndex = _
Convert.ToInt16(LettersArray.GetUpperBound(0) _
* Random1)
Loop
RandomLetter = LettersArray(arrIndex)
If (CType(arrIndex * Random1 * 99, Integer)) Mod 2 <> 0 Then
RandomLetter = LettersArray(arrIndex).ToString
RandomLetter = RandomLetter.ToUpper
End If
sb.Append(RandomLetter)
Else
Do While arrIndex < 0
arrIndex = _
Convert.ToInt16(NumbersArray.GetUpperBound(0) _
* Random1)
Loop
sb.Append(NumbersArray(arrIndex))
End If
Next
Return sb.ToString
End Function
Public Shared Function CheckPassword(ByVal plainText As String, ByVal passwordHash As Byte(), ByVal salt As Byte()) As Boolean
Dim encoding As New System.Text.UTF8Encoding
'Retrieve Salt String from byte array
Dim saltStr As String = encoding.GetString(salt)
Dim hashable As String = Trim(plainText) & Trim(saltStr)
' Convert into hash strings
Dim testhash As String = EncryptStringAsHash(hashable)
Dim realHash As String = encoding.GetString(passwordHash)
' Compare and return result
Return testhash = realHash
End Function
Public Shared Function EncryptStringAsHash(ByVal value As String) As String
Dim encoding As New System.Text.UTF8Encoding
Dim stringBytes As Byte() = encoding.GetBytes(value)
Dim SHhash As SHA512Managed = New SHA512Managed
Dim hash As String = Convert.ToBase64String(SHhash.ComputeHash(stringBytes))
Return hash
End Function
Public Shared Function ConvertStringToByteArray(ByVal value As String) As Byte()
Dim encoding As New System.Text.UTF8Encoding
Return encoding.GetBytes(value)
End Function
End Class
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography
Imports System.Data.OleDb
Imports System.Windows.Forms
Imports System.Data.OleDb.OleDbConnection
Imports System.Data.SqlClient
Public Class Form1
Dim maxrows As Integer
Dim incdec As Integer
Dim con As New OleDb.OleDbConnection
Dim dbprovider As String
Dim dbsource As String
Dim ds As New DataSet
Dim da As OleDb.OleDbDataAdapter
Dim sql As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As New OleDbConnection
Dim dbprovider As String
Dim dbsource As String
dbprovider = "PROVIDER = Microsoft.ACE.OLEDB.12.0;"
dbsource = "Data Source=(localdb)\Projects;Initial Catalog=Test;Integrated Security=True"
con.ConnectionString = dbprovider & dbsource
End Sub
Private Sub btnRegister_Click(sender As Object, e As EventArgs) Handles btnRegister.Click
Dim dbmanager As New DatabaseManager
Dim Data As New DataHandling
'Generate Hash and Salt for password
Dim salt As String = DataHandling.GenerateRandomString
Dim hashable As String = Trim(txtPassword.Text) & Trim(salt) 'txtPassword.Text used to be password
Dim hash As String = DataHandling.EncryptStringAsHash(hashable)
Dim confirmationId As String = System.Guid.NewGuid.ToString
Dim reg As user
reg.Username = txtUsername.Text 'txtUsername.Text used to be username
reg.Password = DataHandling.ConvertStringToByteArray(hash)
reg.Salt = DataHandling.ConvertStringToByteArray(salt)
If dbmanager.UsernameAvailable(txtUsername.Text) Then
dbmanager.Register(txtUsername.Text, txtPassword.Text)
Dim password As String
If txtPassword.Text = String.Empty Then
password = "217tABCDEF42#$tolq"
Else
password = txtPassword.Text
End If
Dim salt As String = GenerateRandomString(12)
Dim hashable As String = Trim(password) & Trim(salt)
MsgBox("Hashable = " & hashable)
Dim hash As String = EncryptStringAsHash(hashable)
CheckPassword(password, ConvertStringToByteArray(hash), ConvertStringToByteArray(salt))
frmAccessGranted.Show()
Me.Hide()
Else
MessageBox.Show("Cannot Register, Username Already Taken!")
End If
End Sub
Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click
txtUsername.Clear()
txtPassword.Clear()
End Sub
End Class
I think your User table User_id value is just missing Identity Specification option. It makes the User_id field to be generated automatically and increased by 1 (by default) for each User you add into
If you have SQL Server management studio you can put this option on:
Right click User table -> Select "Desing" -> Select "User_id" field -> in "Column Propetries" window put "Indentity Specification" option to "Yes" and save
Example SQL Command to create table could be something like this:
CREATE TABLE User (User_id BIGINT IDENTITY NOT NULL, Username NVARCHAR(100) NOT NULL, Password NVARCHAR(100) NOT NULL)
The problem in your code is not in the VB side, it is in the database.
You have set primary key to UserId but you are not passing any values to the userId, you are just passing values to the user name and password.
So there are two ways to solve this issues
you can send userid also from the VB code
you can just make the column UserId as autoincrement field by the following code
CREATE TABLE [dbo].[Test1](
[id] [int] IDENTITY(1,1) NOT NULL,
YourColumnname1 datatype,
YourColumnname2 datatype
)
This works only in the later versions of sqlserver 2008
alter table tablename
alter column columnname
add Identity(100,1)
To know more Click here