ADO.Net Get Inserted Row's ROW ID without designer wizard - sql-server

I have a generic update function that takes a datatable, select query and uses this to update the database tables.It is working fine. I need to know is there a way to get back the inserted row's ID (identity field) by changing something in the below code.
Public Function UpdateDataTable_GetID(ByVal dt As DataTable, ByVal SQL As String, ByVal connString As String) As Integer
Dim conn As SqlConnection = Nothing
Dim cmd As SqlCommand
Dim adp As SqlDataAdapter = Nothing
Dim cmdBuilder As SqlCommandBuilder = Nothing
Dim UpdatedID As Integer
If SQL.Length <= 0 Then
Return False
End If
conn = New Data.SqlClient.SqlConnection(connString)
cmd = New Data.SqlClient.SqlCommand
cmd.Connection = conn
cmd.CommandText = SQL
cmd.CommandType = CommandType.Text
adp = New Data.SqlClient.SqlDataAdapter(cmd)
cmdBuilder = New Data.SqlClient.SqlCommandBuilder(adp)
Try
UpdatedID = Convert.ToInt32(adp.Update(dt)) ' What to do here to get the just inserted ID instead of number of records updated
adp.Dispose()
cmdBuilder.Dispose()
Return UpdatedID
Catch ex As System.Data.SqlClient.SqlException
' Closing connection
Return -1
Finally
End try
End function
I am aware of solutions wherein I can append "select scope_identity()" to the insert Command of data adapter's query using designer as well as editing the adapter's insertcommand text and then doing an ExecuteScalar(). I want to know if the generic adapter.Update() can be tweaked to get the inserted row's ID.

you can subscribe to this event in code like this : (C# I dont know VB)
adp.RowUpdated += adapter_RowUpdated;
and write the event yourself :
void adapter_RowUpdated(object sender, SqlRowUpdatedEventArgs e)
{
if (e.StatementType == StatementType.Insert)
{
object id = e.Command.Parameters["#ID"].Value;
e.Row[_identityFieldName] = id;
}
}
In this example the following has been added to the commandtext first :
SET #ID = SCOPE_IDENTITY()
and a private variable _identityFieldName has been filled.
Maybe this can help you.
EDIT: I noticed you also use an SqlCommandBuilder that makes things easier to add the Scope identity :
SqlCommand inserter = new SqlCommand();
inserter = cmdBuilder.GetInsertCommand(true).Clone();
inserter.CommandText += " SET #ID = SCOPE_IDENTITY()";
SqlParameter param = new SqlParameter();
param.Direction = ParameterDirection.Output;
param.Size = 4;
param.DbType = DbType.Int32;
param.ParameterName = "#ID";
inserter.Parameters.Add(param);
adp.InsertCommand = inserter;

Related

How to pass dynamic parameter from SQL query to the SqlCommand after user input on the SQL query

all. I am facing an issue on how to pass the dynamic parameter value from SQL query, that will be entered by the user into the textbox, to the SQL command to search on the parameter value on the datagridview datatable.
For my project, a textbox will be provided for the user to key in the SQL query dynamically to search on the database data. If the user keys in SQL query like
select *
from table
where a = #a
The user can search on #a parameter value; if the user keys in SQL query like
select *
from table
where a = #a and b = #b
The user can search the #a and #b parameter values by using textbox, which means that the parameter number that had been entered by the user needs to be calculated, retrieved, passed to the SQL command and allow the user to filter on the parameter by using textbox provided.
However, currently, due to the #a parameter and #b parameter will be key in by the user dynamically during runtime, so I faced difficulty to declare/define the parameter name on the cmd.Parameters.AddWithValue() statement.
Can anyone help me to solve my problem by providing me some solutions on codes? I had been stuck on this issue for a few days already. Thank you for all the help!
The code I had tried:
Private Sub btn1_Click(sender As Object, e As EventArgs) Handles btn1.Click
Sql = TextBox4.Text
Try
'open database
Dim con As New SqlConnection(dbstring)
con.Open()
Dim cmd As New SqlCommand(Sql, con)
If param IsNot Nothing Then
For Each para As SqlParameter In param
'cmd.Parameters.Add(para)
For m As Integer = 0 To param.Count - 1
cmd.Parameters.Add(New SqlParameter With {.ParameterName = para.ParameterName(m),
.Value = para.Value(m),
.SqlDbType = SqlDbType.NVarChar,
.Size = 99})
Next
cmd.ExecuteNonQuery()
Next
End If
Using sda = New SqlDataAdapter()
sda.SelectCommand = cmd
cmd.CommandText = Sql
Sql = cmd.ExecuteScalar()
Using ds As DataSet = New DataSet()
sda.Fill(ds)
con.Close()
DataGridView1.DataSource = ds.Tables(0)
End Using
End Using
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Screenshot of Window App Formhad been provided as a reference.
To avoid SQL Injection, im usally doing like this:
Dim text1 As String = "text1"
Dim objComm As SqlCommand = New SqlCommand
objComm.Parameters.AddWithValue("#text1", text1)
objComm.CommandText = "SELECT * FROM TABLE WHERE Text1 = #text1"
I am not sure why you would want the user to write Select statements. I assume this query is on a single table where you know the field names, types and field sizes where applicable. I made up the these items. You will have to check your database to get the correct information.
I used Optional parameters in case you have other datatypes like Booleans or numbers where you can supply the defaults. To pass no value for the parameter just leave a blank but insert the appropriate commans.
Private Function GetSearchResults(Optional FirstName As String = "", Optional LastName As String = "") As DataTable
Dim dt As New DataTable
Using con As New SqlConnection(dbstring),
cmd As New SqlCommand()
Dim sb As New StringBuilder
sb.Append("Select * From SomeTable Where 1 = 1")
If FirstName <> "" Then
cmd.Parameters.Add("#a", SqlDbType.NVarChar, 100).Value = FirstName
sb.Append(" And FirstName = #a")
End If
If LastName <> "" Then
cmd.Parameters.Add("#b", SqlDbType.NVarChar, 100).Value = LastName
sb.Append(" And LastName = #b ")
End If
sb.Append(";")
Debug.Print(sb.ToString)
cmd.CommandText = sb.ToString
cmd.Connection = con
con.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Alternative useage:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt = GetSearchResults(TextBox1.Text, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim dt = GetSearchResults(, TextBox2.Text)
DataGridView1.DataSource = dt
End Sub
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim dt = GetSearchResults(TextBox1.Text, )
DataGridView1.DataSource = dt
End Sub

Fetching data from database into text boxes

I have designed a SQL Server database app in which I fetch data from database and then insert in text boxes. I use a function to fetch data in data table from database and then I populate textboxes. I have to use this coding again and again:
If Dt.Rows.Count > 0 Then
TxtCust_Id.Text = Dt.Rows(0).Item(0)
TxtCust_City.Text = Dt.Rows(0).Item(1)
TxtCust_Area.Text = Dt.Rows(0).Item(2)
Else
TxtCust_Id.Text = String.Empty
TxtCust_City.Text = String.Empty
TxtCust_Area.Text = String.Empty
End if
Text boxes names changes according to query tables. My question is. Is it possible to make a function or procedure to populate data in text boxes from datatable using loops or any other method? Thanks in advance.
Shared Function ExecuteSelectDt(ByVal SelectCommand As String) As DataTable
Cmd = New SqlClient.SqlCommand
Sda = New SqlDataAdapter
' Dt = New DataTable
Try
DBConnection() ' Database connection details
Sda = New SqlDataAdapter(SelectCommand, Con)
Dim dt2 As New DataTable
Sda.Fill(dt2)
CloseConnection()
Return dt2
Catch ex As Exception
CloseConnection()
MsgBox(ex.Message)
Return dt
End Try
End Function
Private Sub TxtCust_Name_Leave(sender As Object, e As EventArgs) Handles TxtCust_Name.Leave
SQuery = "select Cust_Id, Cust_City, Cust_Area from TBLCustommers where Cust_Name= '" & TxtCust_Name.Text & "'"
Dt = Nothing
Dt = BM_Class_Liberary.SQLSereverDB.ExecuteSelectDt(SQuery)
If Dt.Rows.Count > 0 Then
TxtCust_Id.Text = Dt.Rows(0).Item(0)
TxtCust_City.Text = Dt.Rows(0).Item(1)
TxtCust_Area.Text = Dt.Rows(0).Item(2)
Else
TxtCust_Id.Text = String.Empty
TxtCust_City.Text = String.Empty
TxtCust_Area.Text = String.Empty
End if
End Sub
'create and populate list
dim txtBoxes as new List(of TextBox)();
for each ctrl as Control in Form.Controls
if ctrl.GetType() Is GetType(TextBox) then txtBoxes.Add(ctrl)
next
' then do this when you get DataTable
dim theRow as DataRow = dt.Rows(0); ' whatever logic you have to getting needed row
for each col as DataColumn in dt.Columns
' use system.linq
txtBoxes.First(function(tb) tb.Name = col.ColumnName).Text = theRow(col.ColumnName).ToString()
next
Note, when theRow(col.ColumnName) is DBNull.Value, ToString will return string.Empty, which is fine because .Text can't have Nothing
Also, I used First because I did it with the premise that each column has text box.
Or, using the dictionary. Even better, I think
'create and populate dictionary
dim txtBoxes as new Dictionary(of string, TextBox)();
for each ctrl as Control in Form.Controls
if ctrl.GetType() Is GetType(TextBox) then txtBoxes.Add(ctrl.Name, ctrl)
next
' then do this when you get DataTable
dim theRow as DataRow = dt.Rows(0); ' whatever logic you have to getting needed row
for each col as DataColumn in dt.Columns
txtBoxes(col.ColumnName).Text = theRow(col.ColumnName).ToString()
next

VB.NET Inserting data into database from data view grid

I would like to ask is there anyway I can improve my speed when inserting all my data that is from the data grid.
For example:
I have 10,000 data currently needed to insert to the database sql server.
Now, I would like to insert all the data into the database.
But I feel that it would be slow.
Can I do it without using for loop?
Dim chk_cmd As SqlCommand
Dim chk_con As SqlConnection
Dim checker As SqlDataReader
Dim chkint As Integer = 0
Dim constring As String = "Data Source=exmag\sqlexpress;Initial Catalog=Stock;Integrated Security=true;"
Try
For Each row As DataGridViewRow In DataGridView1.Rows
chk_con = New SqlConnection(constring)
chk_con.Open()
chk_cmd = New SqlCommand("SELECT stockId FROM stock WHERE stockId = '" & row.Cells("stockId").Value & "'", chk_con)
checker = chk_cmd.ExecuteReader(CommandBehavior.CloseConnection)
If checker.HasRows Then
chkint += 1
Else
Using con_insert As New SqlConnection(constring), cmd_insert As New SqlCommand("INSERT INTO stock VALUES(#stockId,#id_android,#itemCode,#quantity)", con_insert)
cmd_insert.Parameters.AddWithValue("#stockId", row.Cells("stockId").Value)
cmd_insert.Parameters.AddWithValue("#id_android", row.Cells("id_android").Value)
cmd_insert.Parameters.AddWithValue("#itemCode", row.Cells("itemCode").Value)
cmd_insert.Parameters.AddWithValue("#quantity", row.Cells("quantity").Value)
con_insert.Open()
cmd_insert.ExecuteNonQuery()
con_insert.Close()
End Using
End If
Next
Catch ex As SqlException
If ex.Number.Equals(2627) Then
MsgBox("Primary Key DUPLICATED/Some Data are currently in the table.")
End If
End Try
MsgBox(chkint & " Data has duplicated primary key!")
You can update a database using a DataTable and DataAdapter
A brief online below.
// con = SqlConnection '
// queryString = your SELECT query
Using da As New SqlDataAdapter()
da.SelectCommand = New SqlCommand( _
queryString, connection)
Dim dt As New DataTable("TABLE_NAME")
da.Fill(dt)
// Loop through your collection
// Add new Row to datatable
// Populate new row
Dim drow As DataRow = dt.NewRow()
drow("Example Field") = "Example String"
// Update database
dt.Add(drow)
da.update(dt)
End Using
N.B. Used double-slash instead of an apostrophe for comments as SO seems to be highlighting syntax incorrectly with apostrophes.
Here's one way of doing this; I use it to transfer spreadsheets.
I agree with jmcilhinney that getting 10000 records in a grid is pointless.
// create a datatable
Dim dt_eff As New DataTable
dt_eff.Columns.Add("Element", GetType(String))
dt_eff.Columns.Add("Eff", GetType(Decimal))
dt_eff.PrimaryKey = New DataColumn() {dt_eff.Columns("Element")}
// fill the datatable
For row As Integer = 4 To 50
newRow = dt_eff.NewRow
newRow("Element") = wsComp.Cells(row, 1).Value.ToString
newRow("Eff") = CDec(wsComp.Cells(row, 6).Value)
dt_eff.Rows.Add(newRow)
Next
// send the datatable to a sp on SQL SERVER
Dim param As SqlClient.SqlParameter
Using selectcmd As New SqlClient.SqlCommand("[dbo].[LoadingTable_IntegrateIncoming]", trans.Connection, trans)
selectcmd.CommandType = CommandType.StoredProcedure
param = selectcmd.Parameters.AddWithValue("#Efficiencies", dt_eff)
param.SqlDbType = SqlDbType.Structured
selectcmd.ExecuteNonQuery()
End Using
// on the server side: declare a table type
CREATE TYPE [dbo].[TVP_Efficiencies] AS TABLE(
[Element] [nvarchar](5) NOT NULL,
[Eff] [decimal](18, 4) NOT NULL,
PRIMARY KEY CLUSTERED
(
[Element] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
// and create a stored proc that consumes the datatable
CREATE PROCEDURE [dbo].[LoadingTable_IntegrateIncoming]
#Efficiencies TVP_Efficiencies readonly
AS
BEGIN
SET NOCOUNT ON;
insert into efficiencies
select * from #Efficiencies
END

VB.NET Insert DataGridView contents into Database

Problem:
I need to dump the contents of my DataGridView into a SQL Server Database Table. I've got the datagridview loading fine, no problems there. I'm just not familiar enough with VB.NET to understand how to get that data into a DB table.
Code: (so far)
Dim connection As New Data.SqlClient.SqlConnection
Dim dataAdapter As New Data.SqlClient.SqlDataAdapter
Dim command As New Data.SqlClient.SqlCommand
Dim dataSet As New Data.DataSet
connection.ConnectionString = "Server= server; Database= DB; integrated security=true"
command.CommandText = "INSERT INTO <table> (Col1, Col2, Col3, Col4) VALUES (#Name, #Property, #Value, #Date)"
dataAdapter.InsertCommand.Parameters.Add("#ServerName", SqlDbType.VarChar)
dataAdapter.InsertCommand.Parameters.Add("#Property", SqlDbType.VarChar)
dataAdapter.InsertCommand.Parameters.Add("#Value", SqlDbType.VarChar)
dataAdapter.InsertCommand.Parameters.Add("#CaptureDate", SqlDbType.DateTime)
For i As Integer = 0 To DataGridView.Rows.Count - 1
dataAdapter.InsertCommand.Parameters(0).Value = dgvServerConfig.Rows(i).Cells(0).Value
dataAdapter.InsertCommand.Parameters(1).Value = dgvServerConfig.Rows(i).Cells(1).Value
dataAdapter.InsertCommand.Parameters(2).Value = dgvServerConfig.Rows(i).Cells(2).Value
dataAdapter.InsertCommand.Parameters(3).Value = dgvServerConfig.Rows(i).Cells(3).Value
Next
connection.Open()
command.Connection = connection
dataAdapter.SelectCommand = command
What am I missing here? Nothing is getting inserted into my table. Any help would be appreciated. Like I said, I'm not very familiar with VB so take it easy on me.
Well, you need to execute the command, not simply add to the DataAdapter
Also, as it coded now, you don't need the DataAdapter at all.
Dim connection As New Data.SqlClient.SqlConnection
Dim command As New Data.SqlClient.SqlCommand
connection.ConnectionString = "Server= server; Database= DB; integrated security=true"
command.CommandText = "INSERT INTO <table> (Col1, Col2, Col3, Col4) VALUES (#Name, #Property, #Value, #Date)"
command.Parameters.Add("#ServerName", SqlDbType.VarChar)
command.Parameters.Add("#Property", SqlDbType.VarChar)
command.Parameters.Add("#Value", SqlDbType.VarChar)
command.Parameters.Add("#CaptureDate", SqlDbType.DateTime)
connection.Open()
command.Connection = connection
For i As Integer = 0 To DataGridView.Rows.Count - 1
command.Parameters(0).Value = dgvServerConfig.Rows(i).Cells(0).Value
command.Parameters(1).Value = dgvServerConfig.Rows(i).Cells(1).Value
command.Parameters(2).Value = dgvServerConfig.Rows(i).Cells(2).Value
command.Parameters(3).Value = dgvServerConfig.Rows(i).Cells(3).Value
command.ExecuteNonQuery()
Next
However this calls the database to insert one row at a time. I think it is better to look at the SqlDataAdapter.Update method that resolves the insert/update work with just one call.
Using the SqlDataAdapter.Update method, requires that you save in a global variable the Adapter used at the moment in which you have filled the DataGridView and add a SqlCommandBuilder that generates for you the InsertCommand, UpdateCommand and DeleteCommand
' At form loading'
Dim adapter As New OleDbDataAdapter()
adapter.SelectCommand = New OleDbCommand("SELECT COL1, COL2,COL3,COL4 FROM TABLE", connection)
Dim builder As OleDbCommandBuilder = New OleDbCommandBuilder(adapter)
connection.Open()
Dim myTable As DataTable = New DataTable
adapter.Fill(myTable)
DataGridView.DataSource = myTable
....
' at grid save'
Dim myTable = CType(DataGridView.DataSource, DataTable)
adapter.Update(myTable)
For each object in your GridView, you need to find it and determine its value. So for example,
DropDownList ddlToLoc = (DropDownList)gvMovesMod.Rows[0].FindControl("ddlToLoc");
Then, determine ddlToLoc's SelectedValue and insert to database
You can call: command.ExecuteNonQuery to insert data to the DB.
More info here
TRY THIS METHOD
For index As Integer = 0 To DataGridView1.RowCount - 1
Dim connectionString = "Data Source=localhost;port=3306;Initial Catalog=hasna;User Id=root;password=''; Convert Zero Datetime=True"
Dim query0 = "insert into itemledgerfinal(Date,BillDate,BillNo,ItemName,GST,Rate,MRP,TotalQty,PurchaseRate,WholesaleRate,Total,Type,OpeningBalance,Purchase,Sale,ClosingBalance,ID) values(#Date,#BillDate,#BillNo,#ItemName,#GST,#Rate,#MRP,#TotalQty,#PurchaseRate,#WholesaleRate,#Total,#Type,#OpeningBalance,#Purchase,#Sale,#ClosingBalance,#ID)"
Dim connection0 As New MySqlConnection(connectionString)
Dim command0 As New MySqlCommand(query0, connection0)
command0.Parameters.AddWithValue("#Date", DataGridView1.Rows(index).Cells(0).Value)
command0.Parameters.AddWithValue("#BillDate", DataGridView1.Rows(index).Cells(1).Value)
command0.Parameters.AddWithValue("#BillNo", DataGridView1.Rows(index).Cells(2).Value)
command0.Parameters.AddWithValue("#ItemName", DataGridView1.Rows(index).Cells(3).Value)
command0.Parameters.AddWithValue("#GST", DataGridView1.Rows(index).Cells(4).Value)
command0.Parameters.AddWithValue("#Rate", DataGridView1.Rows(index).Cells(5).Value)
command0.Parameters.AddWithValue("#MRP", DataGridView1.Rows(index).Cells(6).Value)
command0.Parameters.AddWithValue("#TotalQty", DataGridView1.Rows(index).Cells(7).Value)
command0.Parameters.AddWithValue("#PurchaseRate", DataGridView1.Rows(index).Cells(8).Value)
command0.Parameters.AddWithValue("#WholesaleRate", DataGridView1.Rows(index).Cells(9).Value)
command0.Parameters.AddWithValue("#Total", DataGridView1.Rows(index).Cells(10).Value)
command0.Parameters.AddWithValue("#Type", DataGridView1.Rows(index).Cells(11).Value)
command0.Parameters.AddWithValue("#OpeningBalance", DataGridView1.Rows(index).Cells(12).Value)
command0.Parameters.AddWithValue("#Purchase", DataGridView1.Rows(index).Cells(13).Value)
command0.Parameters.AddWithValue("#Sale", DataGridView1.Rows(index).Cells(14).Value)
command0.Parameters.AddWithValue("#ClosingBalance", DataGridView1.Rows(index).Cells(15).Value)
command0.Parameters.AddWithValue("#ID", DataGridView1.Rows(index).Cells(16).Value)
connection0.Open()
command0.Connection = Connection
command0.ExecuteNonQuery()
Next

Inserting data into SQL Server database using VB.Net

I am currently using HDI Membership provider and the design looks as shown below:
Now I am trying to create a new user and insert those values into the database as shown below:
Try
Dim connectionString As String = "Data Source=.\sqlexpress;Initial Catalog=HDIMembershipProvider;Integrated Security=True"
Using cn As New SqlConnection(connectionString)
cn.Open()
Dim cmd As New SqlCommand()
cmd.CommandText = "INSERT INTO Users VALUES(#Username,#Password,#Email,#PasswordQuestion,#PasswordAnswer)"
Dim param1 As New SqlParameter()
param1.ParameterName = "#Username"
param1.Value = txtUsername.Text.Trim()
cmd.Parameters.Add(param1)
Dim param2 As New SqlParameter()
param2.ParameterName = "#Password"
param2.Value = txtPassword.Text.Trim()
cmd.Parameters.Add(param2)
Dim param3 As New SqlParameter()
param3.ParameterName = "#Email"
param3.Value = txtEmail.Text.Trim()
cmd.Parameters.Add(param3)
Dim param4 As New SqlParameter()
param4.ParameterName = "#PasswordQuestion"
param4.Value = txtSecurityQuestion.Text.Trim()
cmd.Parameters.Add(param4)
Dim param5 As New SqlParameter()
param5.ParameterName = "#PasswordAnswer"
param5.Value = txtSecurityAnswer.Text.Trim()
cmd.Parameters.Add(param5)
cmd.Connection = cn
cmd.ExecuteNonQuery()
cn.Close()
End Using
Successlbl.show
Successlbl.show.Text = "Regisration Success."
Catch
Errolbl.Show()
Errolbl.Text = "Your account was not created.Please try again."
End Try
Now the problem is the data is not inserting to the database. I would like to know If anyone can point me where I'm going wrong?
Your insert statement is incorrect - since you are not specifying any field names you should be supplying values for all columns.
The fix is to supply the names of the columns you are insert into.
The screenshot also shows that there is a required ApplicationName column, so unless it has a DEFAULT defined, you will need to supply that as well.
Assuming you have a DEFAULT defined on ApplicationName:
cmd.CommandText = "INSERT INTO Users ( Username, Password, Email, PasswordQuestion, PasswordAnswer) VALUES(#Username,#Password,#Email,#PasswordQuestion,#PasswordAnswer)"

Resources