Asp.net parametized SQL Query with DataAdapter/Dataset - asp.net

What I want to do is to look for the text that is entered on textbox4 assigned to Valor and display if found, the below code is working but I want to use parametized queries (security reasons) and I don't know how to modify my existing code to get it done. (eg, 123-A)
I will look for "123-A" but in the current code I got an error of "invalid column A", the SQL column that I will be looking "123-A" is "ID_LALTest"
Try
' *--------search by Unique ID-------*
Dim CON As New SqlConnection
Dim DA As New SqlDataAdapter
Dim DS As New DataSet
Dim SQL As String
Dim Valor As String
Valor = TextBox4_SearchData_LALTest.Text
CON.ConnectionString = "not displayed"
CON.Open()
SQL = "SELECT ID_LALTest, LALTest_SeqRef_CH, LALTest_SeqRef_Year FROM LALTest WHERE ID_LALTest=#Valor"
DA = New SqlDataAdapter(SQL, CON)
DA.SelectCommand.Parameters.AddWithValue("#Valor", Valor)
DA.SelectCommand.ExecuteNonQuery()
DA.Fill(DS, 0)
If DS.Tables(0).Rows.Count > 0 Then
' *--------Found, Display Data Grid-------*
Label2_SearchData_LALTest.Visible = False
GridView2_SearchData_LALTest.Visible = True
GridView3_SearchData_LALTest.Visible = True
GridView1_SearchData_LALTest.Visible = False
Else
Label2_SearchData_LALTest.Text = "Record Not Found"
Label2_SearchData_LALTest.Visible = True
GridView2_SearchData_LALTest.Visible = False
GridView3_SearchData_LALTest.Visible = False
GridView1_SearchData_LALTest.Visible = False
End If
con.dispose()
Catch ex As Exception
MsgBox(Err.Description)
End Try

Yup, you are wide-open for sql-injection. Depending on different databases (you just have SQL, but is that SQL-Server, MySQL, an Access/SQL database, etc).
Anyhow, it's not too far off from what you have. Not specializing in VB, I'll give you some pseudo-code for it...
Change your query, and put in a "place-holder" for the "variable" you want to apply from the input... Ex:
"select (your fields) from (yourtable) where ID_LALTest = #parmValor"
Then, add the parameters to your sql command created for your data adapter... something like...
DA.SelectCommand.Parameters.Add( "#parmValor", theInputFromYourVariable );
Now, if you have multiple conditions you want to apply, just keep adding "#someParm" value and add the parameters IN THE SAME ORDER as they exist in the query... I've heard from others in the past, that just the ordinal sequence of parameters not matching the query can/does cause problems... such as data type expectations too.

Related

Multiple Values in DropdownList.DataTextField Not Working

I have the below code which is populating a dropdownlist in ASP.NET. When I use a single value, everything works like a charm, but I want the DataTextField to use two fields coming from the database, not one. Any assistance would be greatly appreciated. I have tried several ways, but nothing seems to work :(
Dim connstr As String = Session("ConnStrEP")
Using con As New SqlConnection(connstr)
Using cmd As New SqlCommand()
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "GetWaivers"
cmd.Connection = con
con.Open()
Dim dr As SqlDataReader = cmd.ExecuteReader()
dr.Read()
Code.DataSource = dr
Code.DataTextField = String.Format("{0}, {1}", Code.SelectedValue("tblWVCode").ToString(), Code.SelectedValue("tblWVDesc").ToString())
Code.DataValueField = "tblWVDesc"
Code.DataBind()
dr.Close()
con.Close()
End Using
End Using
UPDATE:
I generated the below SQL, but I am receiving an error when I execute the SQL Server 2008 Stored Procedure. "Invalid operator for data type. Operator equals add, type equals ntext.
"
SELECT TblWvCode, TblWvDesc, (TblWvCode + ' - ' + TblWvDesc) As FullList FROM EP.dbo.WaiverVarianceTbl
Modify the stored proc to concatenate the tblWVCode and tblWVDesc values and return them in a new field, you can then use that field for the DataTextField
You can't do that, you'll need to change your SQL query to return the field on the format you need. DataTextField must be a field or property name.
Your query should looks like this
SELECT
TblWvCode,
TblWvDesc,
(
CAST(TblWvCode as nvarchar(max)) + ', ' + CAST(tblWVDesc as nvarchar(max))
) as FullList
FROM EP.dbo.WaiverVarianceTbl
and then your VB code would be something like this
Code.DataTextField = "FullList"
Code.DataValueField = "tblWVDesc"

DataReader.Read() skips first row of recordset

I am trying to check the value of a field before decided what to input into a drop down list in ASP.net.
I am using datareader.Read() in order to read the recordset so I can do this. However this then skips the first row of data . . The drop down box is basically a list of sizes and colours . . . So currently I am missing the first size.
Here is the code:
Using cmd As New SqlCommand("doGetAllSizesForProduct", oConn)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#id", CType(Request.QueryString("id"), Integer))
oConn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
If dr.HasRows() = True Then
dr.Read()
ddlSize.Visible = True
pnlSize.Visible = True
pnlNoStock.Visible = False
If dr("colour") = "None" Then
ddlSize.DataTextField = "size"
Else
ddlSize.DataTextField = "sizeColour"
End If
ddlSize.DataValueField = "mapperid"
ddlSize.DataSource = dr
ddlSize.DataBind()
Else
End If
dr.Close()
End Using
End Using
I guess either there must be another method other than Read or a way to stop it skipping the first record?
I've never seen a datareader being used as the datasource. What I think is happening is that your first call to dr.Read() is skipping to the first record as expected. However, when you assign the reader as the datasource, it's doing its own dr.Read() logic inside which starts at the next record. This could explain why you're not seeing the first item. Try modifying your code like this to use a DataTable instead (warning, didn't test this):
using dr as SqlDataReader = cmd.ExecuteReader()
if dr.HasRows() then
ddlSize.Visible = True
pnlSize.Visible = True
pnlNoStock.Visible = False
While dr.Read()
dim Value as string = dr("mapperid")
dim Text as string = if(dr("colour") = "None",dr("size"),dr("sizeColour"))
ddlSize.Items.Add(New ListItem(Text, Value))
End While
end if
dr.Close()
end using
How about changing the doGetAllSizesForProduct stored procedure to return two recordsets?
The first recordset can return a single row giving an indication of what type of data is contained in the second recordset, which contains the same content as previously.
you are not supposed to use the DataReader like this, executing a single Read to get the value in the first record then binding the UI control to it like this:
ddlSize.DataValueField = "mapperid"
ddlSize.DataSource = dr
ddlSize.DataBind()
I would personally use a DataTable for binding to a UI control, or try to remove the call to dr.Read() and see how it works.

Dropdown list values repeating

I am using dropdown list values Bound from data base my code
Public Function get_type() As String
'get type
If IsPostBack = False Then
da = New OleDbDataAdapter("select (type) from prod_type", con)
da.Fill(ds, "prod_type")
ddtype.DataSource = ds
ddtype.DataTextField = "type"
ddtype.DataValueField = "type"
ddtype.DataBind()
da.Dispose()
ds.Dispose()
con.Close()
End If
I call this function in page load
Edit: ignore this, it's wrong:
This is a SQL question not a asp.net or VB question.
Your sql won't select unique 'types' from your prod_type table. Execute the following SQL:
select distinct(type) from prod_type
Also read the posting FAQ: https://stackoverflow.com/faq
Modify it like this:
Public Function get_type() As String
'get type
If IsPostBack = False Then
ds.Clear() //new
ddtype.Items.Clear() //new
da = New OleDbDataAdapter("select (type) from prod_type", con)
da.Fill(ds, "prod_type")
ddtype.DataSource = ds
ddtype.DataTextField = "type"
ddtype.DataValueField = "type"
ddtype.DataBind()
da.Dispose()
ds.Dispose()
con.Close()
End If
And if you still have duplicate entries it should be because you have duplicates in the database.
There are two cases where the values would be duplicated in the DropDownList here:
There are duplicated values in the database.
You are calling the function multiple times at the first loading of the page.
You can solve the first case by using DISTINCT in your select statement:
SELECT DISTINCT type FROM prod_type
You can solve the second by setting the value of the TableAdapter.ClearBeforeFill property to true.

checking for duplicate values before attempting insert (ASP.NET)

I have a form where two fields on the first page of the form make up the primary key. I want to check for duplicate values before attempting to insert the record, since I don't want the user to go all the way through the form only to find out they can't submit it. So I'm trying to check for duplicate values when the user tries to go to the next page of the form. I wasn't quite sure how to do it, and sure enough I'm getting an error. ("Object reference not set to an instance of an object.") The problem is apparently in my if statement, "If myValue.Length > 0 Then", but I'm not sure what needs to be in place of that.
Protected Sub CustomValidator1_ServerValidate(ByVal source As Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Handles CustomValidator1.ServerValidate
'get values
Dim checkPrefix = txtCoursePrefix.Text
Dim checkNum = txtCourseNum.Text
'db connectivity
Dim myConn As New OleDbConnection
myConn.ConnectionString = AccessDataSource1.ConnectionString
myConn.Open()
'select records
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix='checkPrefix' AND course_number='checkNum'", myConn)
'execute(Command)
Dim myValue As String = mySelect.ExecuteScalar()
'check if record exists
If myValue.Length > 0 Then
CustomValidator1.ErrorMessage = "some exp text"
CustomValidator1.SetFocusOnError = "true"
CustomValidator1.IsValid = "false"
End If
End Sub
Thought I'd post the final solution:
'select records
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
'execute(Command)
Dim myValue = mySelect.ExecuteScalar()
'check if record exists
If myValue IsNot Nothing Then
CustomValidator1.SetFocusOnError = True
args.IsValid = False
End If
This error indicates that the content of myValue variable is null. If it's null you can't use Length property (or any other property for that matter) on it. You have to check for null explicitly:
If myValue IsNot Nothing Then
EDIT 1
Your sql query is wrong. I don't know what would be the right query, as I don't know your database, but I think you intender to write this:
Dim mySelect As New OleDbCommand("SELECT prefix, course_number FROM tableCourse WHERE prefix=" + checfkPreix + " AND course_number=" + checkNum, myConn)
or something to that effect. You might want to consider using string.Format function for forming the string. And you also need to make sure that there is some kind of protection against SQL Injection, since you form your query from user input. In your case using of OleDbParameter might be appropriate.
Edit 2
You also right to mention that there might be a problem with ExecuteScalar. ExecuteScalar is supposed to return a single value and your select query are returning two (prefix and course_number). Change it so that it returns a single parameter SELECT prefix FROM or simply SELECT 1 FROM and then the rest of the query:
Dim mySelect As New OleDbCommand("SELECT 1 FROM tableCourse WHERE prefix=? AND course_number=?", myConn)
mySelect.Parameters.AddWithValue("#checkPrefix", checkPrefix)
mySelect.Parameters.AddWithValue("#checkNum", checkNum)
Edit 3
You are not setting failed validation properly in your validator.
Add
args.IsValid = False
inside your if statement.
First ExecuteScalar will only return a single value, so in this case you are only going to get the column prefix from the result. Second if there is no match with your query it will return null, so your next length check should account for that scenario:
if String.IsNullOrEmpty(myValue) Then
...
Reference: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
myValue is null if there is no duplicate, so you have to apply .Length only if myValue is not null (which means checking for null only is enough; without .Length)
If Not string.IsNullOrEmpty(myValue) Then
try something like this instead (you will have to adapt it to VB.Net) DBNull is different from Null or Nothing so you have to compare it to both
If myValue <> DBNull and not myvalue is nothing Then

SQLDataReader find value of each row

I used to use datasets instead of sqldatareaders and I used to be able to do something like this
If dataset.tables(0).Rows(0)(1).ToString()) = "N" Then
lbl.Text = dataset.tables(0).Rows(0)(2).ToString())
Else
'Do Nothing
End If
This obviously doesn't work with sqldatareaders.
I have code to see if the SQLDatareader has any rows but was wondering if there was a way to get the value of each row
I'm guessing this is possible and i've had a look around but can't seem to find anything
Dim conn As SqlConnection = New SqlConnection("server='h'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("DECLARE #investor varchar(10), #sql varchar(1000) Select #investor = 69836 select #sql = 'SELECT * FROM OPENQUERY(db,''SELECT * FROM table WHERE investor = ''''' + #investor + ''''''')' EXEC(#sql)", conn)
Dim oDR As SqlDataReader = query.ExecuteReader()
If oDR.HasRows or dataset.tables(0).Rows(0)(1).ToString()) = "N" Then
lbl.Text = dataset.tables(0).Rows(0)(2).ToString())
Else
'Do Nothing
End If
That is the code I have at the moment which obviously doesn't work
Any ideas?
Thanks
When you use the data reader you have to step through each row yourself. Using HasRows is a good start, for it will tell you if the returned result set is empty.
To iterate through the result set you should use the Read() method. It will return true if you are at a row and false when you have moved past the last row.
My Vb is poor so I will give you an example in C# instead:
if (oDR.HasRows && oDR.Read())
{
if (oDR.GetString(0) == "N")
{
lbl.Text = oDr.GetString(1);
}
}
Here I first check that we have a result set with data and then try to move to the first row. If this succeeds I then read the string value of the first column and compare it to "N". If the value is equal to "N" I set the Text property of the lbl variable to the string value of the second column.
This should be equivalent to your algorithm with the dataset. I recommend that you read the MSDN documentation for the SqlDataReader. It is quite good and the example code is useful.

Resources