Situation:
I have a pre-built form that uses two Form Views. One is for pickup and one for delivery. The form can't be changed due to client requirements. The entire form and Form Views use a WizardStep process.
Each side pre-fills in the clients company name and related data such as Pickup Name, address, city, state etc as well as Delivery Info all using the same fields using the same stored procedure.
The stored procedure shows the concat of Name and Address 1 as FullName and the ClientSubCtr. ClientSubCtr is an int field. This id is what populates the correct data to each dropdown.
The dropdown list is not inside the FormView and falls under the form tag.
When testing the connection via the <asp:SqlDataSource> tag everything works in the Configure Data Source and data is returned using the appropriate parameter. The connection for the matching client data uses a basic Select to the table used in the stored procedure. I've tried to use a different stored procedure for the data, but no success there either. I am using SQL Server Express right now locally.
I've tried disabling the asp:SqlDataSource and just use a database connection from page_load, which did not work. I've commented it out as I'm still trying different things. I may be missing some syntax to connect to the dropdown here.
'This did not work
'Using conn As New SqlConnection(connect)
' strSQL = "SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName 'FROM tblClientsSub"
' strSQL = strSQL & " WHERE Account ='" & sessAccount & "'"
' strSQL = strSQL & " ORDER BY FullName ASC"
' conn.Open()
' Using cmd As New SqlCommand(strSQL, conn)
' cmd.Parameters.AddWithValue("#Account", sessAccount)
' cmd.CommandText = strSQL
' cmd.ExecuteNonQuery()
' Dim dr As SqlDataReader = cmd.ExecuteReader()
' If dr.HasRows Then
' Do While (dr.Read())
' ClientSubCtr = dr.GetValue(0)
' FullName = dr.GetValue(1)
' s1_cboAcct.DataTextField = FullName
' s1_cboAcct.DataValueField = ClientSubCtr
' s1_cboAcct.DataBind()
'Corrected Databind still does not work
' Loop
' Else
' dr.Close()
' End If
' End Using
'End Using
Additional info: Prior to using this I have two Pre-Render functions. One for Pickup and Delivery which fills in what my client calls a Docket. It shows the info that was pre-filled in with the initial loading or by the Selected Change on the dropdown and or where the client manually added or changed something, thus sending the correct information to the database for eventual download.
Note: This was originally written making OLEDB ACE connections to my clients Go Daddy account. Go Daddy moved the site to a new server and will no longer support ACE 12.0. We begged for them to change this. Thus, the move to SQL Server.
When I get what I believe is the data getting load I get an error in my pre-render on this tag. I've purposely commented out all the pre-render to see what was returned in regards to errors. No errors are return and the general form returns showing the drop-down but no data and the field in the FormView can't be seen. In other words not even the labels are showing. I've checked all asp:sqldatasource settings.
' If IsNothing("txtcboAcct.Text") Then
'lblDocketPUName.Text = ""
(I've tried using Request.form here, but data isn't loaded so I get nothing.) and commented out the If Else End If
' Else
' lblDocketPUName.Text = CType(frmViewPUClient.FindControl("txtcboAcct"), TextBox).Text
(This is where I get an error where the object is not found because neither the data for the dropdown is loading or the data for the forms.)
' End If
I know this is a lot to digest, but I'm totally baffled why this works perfectly using OLEDB and Access 2007 but when switching to SQL Server and the exact tables named the same, it does not. Any insight to why the stored procedure won't fill in the dropdown or why even my code in page_load wouldn't fill in the drop-down would be helpful. I've updated all parameters to use the # symbol.
Here is the stored procedure:
'ALTER PROCEDURE [dbo].[qryFullNameAddr]
'#Account nvarchar(10) OUTPUT
'AS
' -- Add the parameters for the stored procedure here
'DECLARE #ClientSubCtr int
'DECLARE #Name nvarchar(50)
'DECLARE #Address1 nvarchar(125)
'DECLARE #FullName nvarchar(255)
'BEGIN
' -- SET NOCOUNT ON added to prevent extra result sets from
' -- interfering with SELECT statements.
' SET NOCOUNT ON;
' /*Write statements for procedure here */
'SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName
'FROM tblClientsSub
'WHERE #Account=#Account
'ORDER BY FULLNAME, ADDRESS1 ASC
'end
Well, first I would back the truck up so to speak.
I would create a blank new test web page. Put in a dropdown list, and get it working.
Next up:
You don't need to loop for a drop down list. You can feed a dropdown a TABLE. And that table can be a query, or perhaps a stored procedure.
So, for starters, lets display a Hotel List in a drop down. And like most drop downs, there are often two columns the hidden "id" or often "PK" of the row, and then the display text.
So, our blank we page, we drop in a drop down list. Say like this:
<form id="form1" runat="server">
<div>
<asp:DropDownList ID="DropDownList1" runat="server"
DataTextField="HotelName"
DataValueField="ID" Height="22px" Width="219px">
</asp:DropDownList>
</div>
</form>
And now the code to fill - and as noted ALWAYS ALWAYS load only on first page load - that is PostBack = false - (break that rule, and you can't really even make a correctly working web page).
Ok, so our code is now this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData
End If
End Sub
Sub LoadData()
Using con As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String = "SELECT ID, HotelName from tblHotels ORDER BY HotelName"
Using cmdSQL As SqlCommand = New SqlCommand(strSQL, con)
con.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
DropDownList1.DataSource = rstData
DropDownList1.DataBind()
DropDownList1.Items.Insert(0, New ListItem("", "")) ' optional blank starting select
End Using
End Using
End Sub
That's it!!!
Also, don't know why so many code examples set the DataTextField and DataValue field in code? Why???? Just use the property sheet - little need to put such things in the code side - ESPECIALLY when the property sheet can do that for you!!!
Next up? Well, everyone always on SO piles in about how you should use parameters in such code in place of concatemer strings. This is correct, but if you code with parameters, then you can OFTEN reduce code, and CLEAN UP your sql anyway.
In place of say a messy sql string, you remove the text ('quotes'), and numbers (no quotes), and this even works better for dates.
So this benefit is near as great as the issue of sql injection issues.
(and to be fair, you noted a stored procedure, and it not working, so clearly you decided to try anything here - I get that approach).
So, your code snip? I would code it this way:
Dim strSQL As String =
"SELECT ClientSubCtr,CONCAT(Name, Address1) AS FullName FROM tblClientsSub " &
"WHERE Account = #Acc " &
"ORDER BY FullName ASC"
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
cmdSQL.Parameters.Add("#Acc", SqlDbType.NVarChar).Value = sessAccount
conn.Open()
s1_cboAcct.DataSource = cmdSQL.ExecuteReader
s1_cboAcct.DataBind()
End Using
End Using
Now is that not MUCH more readable?
And in fact cut + paste your code?
I noticed this:
SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName 'FROM
Wait? what is the ' right before the FROM???? You have a stray ', don't you?
Maybe that was a code cut + paste error, maybe not. But the REAL POINT?
By using parmaters we go nuclear on the single, double quotes, and all that jazz.
in other words, sure, avoiding string concntatiion of values is important for reasons of sql injection, but REALLY MUCH more valuable is how we don't have to bother with all those quotes and stuff. The result is it is MUCH HARDER to miss or mess up!!!
The other issue of course is by using the parameters as per above?
Well, we get intel-sense. And if I have several more, then in VS I just hit ctrl-d to dupplie the line. I actually wind up TYPING LESS code then If I attempted to introduce those values right into the sql!!! Imagine that - eaiser to read, and even less typing of code!!! - all this amounts up to much less error prone code. I mean, one missing quote like ' or a extra one? You in trouble and will waste time!!
You ALSO note that I did not even use a reader into a DataTable, and just shoved the reader results RIGHT into the combo box - saves even more code!!!!
However, while a dropdown, listview, gridview (and many more) can ALL accept DataSource as a cmdSQL.ExecuteReader as I did?
I still STRONG recommend you use my first version for Grids/list views etc. (and a HUGE reason exists for this!!!). (data pagers don't work if you feed a gridview a reader, but a table they work fine, and also the data bind events (not often used for combo box, but VERY often used for grids often needs the data source - so for this combo? Sure you can skimp out on the two extra lines of code (to create a DataTable and load it). But for a gridview, don't use that cool short cut I used above by feeding the reader directly into grids or listviews - but for combos, perfect fine.
So, with above, and after running above code, we have this:
As noted, if you DO test or decide to load up a combo box, and NOT use say a DataSoruce control dropped into the markup (I don't like those things all that much), then MAKE SURE you put and ONLY call the loading of such controls inside the If Not IsPostBack code stub. DO NOT EVER fail to follow this rule.
Again: do NOT EVER EVER fail to follow this rule.
Why?
Becuase any other button or any other thing you EVER will place on that page may well need to do a post-back (say even a few simple buttons). So, if you say select a combo box, fill out some other things, and have some button (and a button click event with code behind)?
Wel, keep in mind that page load ALWAYS FIRES each post-back!!!!
So, if your code re-loads say the combo box, then it going to blow out any existing selecting the user has for that combo (or grid or just about anything else!!!). So, you have to write your code in a way that it will "assume" and "work" and "survive" post-backs. So your loading up of controls thus should only be ONE time, and on the first page load - hence my HUGE LONG narrative of how vast important it is to follow this simple rule.
I've very new to ASP.net. However, I am currently working on a project and I am trying to change the table that this ASP.net application is pointing to.
I know that the key to doing this lies in figuring out how the following is set in my Default.aspx.vb file:
Dim cmdText as String = "[up_getPrevention]"
Using command As SqlCommand = New SqlCommand(cmdText, conn)
command.CommandType = CommandType.StoredProcedure
command.Parameters.AddWithValue("#userid", usr)
Does anyone know what the [] means in the statement above? I know that typically the SQL statement (ie. SELECT) is within those double quotes...
Thanks for your help!
if the sp name we are writing is a keyword of SQL itself then we need to put [] at start and end of it...
Like 'Table'
I'm still somewhat new to ASP.NET and VB, and I found out that it's vastly different from the ASP I learned where I used Recordset to extract data from the database. Can someone give me some pointers on how to extract data from a database? Here is what I used to at least connect:
Dim conn As OdbcConnection
conn = New OdbcConnection("DSN=southwind")
Dim mystring as String = "SELECT GroupName FROM Group"
Dim cmd As OdbcCommand = New OdbcCommand(mystring, conn)
conn.Open()
Dim reader As OdbcDataReader = cmd.ExecuteReader()
The last line gives me an error saying:
Exception Details: System.Data.Odbc.OdbcException: ERROR [42000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Incorrect syntax near the keyword 'Group'.
But since I don't quite understand ASP.NET completely, not too sure what it means even though the syntax looks fine. Removing that line runs the code just fine. How would I display all the contents from the GroupName column in table Group?
EDIT: Thanks everyone, I completely forgot that Group was reserved in SQL.
Group is a keyword in SQL, you need to wrap it in square brackets like this,
SELECT GroupName FROM [Group]
This would assume the Group to be a name of the table, instead of a key word; of GROUP BY clause.
Group is a keyword in SQL. If your table name or column names referenced in your query are keywords, you can enclose them in brackets.
Dim mystring as String = "SELECT GroupName FROM [Group]"
I am trying to write a paramaterized update query to insert values into an Sql Server Express Database. The query I have written is:
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandText = "update tblposts set title=#ptitle, pdate=#pd,
content=#pcontent where pid=#p"
cmd.Parameters.AddWithValue("ptitle", txtTitle.Text)
cmd.Parameters.AddWithValue("pcontent", txtcontent.InnerText)
cmd.Parameters.AddWithValue("pd", DateTime.Now.ToString)
cmd.Parameters.AddWithValue("p", postid)
On running cmd.ExecuteNonQuery, I get number of rows affected as 1, but the change is not reflected in the database.
On printing the query using Debug.Write, I get the query not with the parameter values, but the names of the parameters itself (ie. #pcontent, #title etc)
What can be the mistake here?
In you're AddWithValue you need to include the # symbol on the front of the parameter, so:
cmd.Parameters.AddWithValue("#ptitle", txtTitle.Text)
cmd.Parameters.AddWithValue("#pcontent", txtcontent.InnerText)
cmd.Parameters.AddWithValue("#pd", DateTime.Now.ToString)
cmd.Parameters.AddWithValue("#p", postid)
I'm guessing that it's executing correctly but there where clause is blank, so perhaps updating a blank row.
Anyway, try the above and it should update as expected.
Edit to Add
The CommandText will always only have the #value in there, it will not substitue the parameter values into the string.
You would need to loop through the cmd.Parameters collection to write out the values.
I am constructing a search function in a class to be used by several of our asp pages. The idea is simple, take a search term from the user and query the database for the item. Currently I am doing this the wrong way, which is vulnerable to SQL injection attacks (and ELMAH is in there to save the day if something goes wrong):
Public Shared Function SearchByName(ByVal searchterm As String) As DataTable
SearchByName = New DataTable
Dim con As New OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OracleDB").ConnectionString)
Try
con.Open()
Dim SqlStr As String = "select ID_ELEMENT, ELEMENT_NAME from table_of_elements where upper(ELEMENT_NAME) like upper('%" & searchterm & "%')"
Dim cmd As New OracleCommand(SqlStr, con)
SearchByName.Load(cmd.ExecuteReader)
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext().Raise(ex)
End Try
con.Close()
con.Dispose()
Return SearchByName
End Function
String concatenation is BAD. Next thing you know, Bobby Tables wrecks my system.
Now, the correct way to do this is to to make a proper oracle variable, by putting :searchterm in the string and adding the following line:
cmd.Parameters.Add(New OracleParameter("SEARCHTERM", searchterm))
The problem is since I am using a like statement, I need to be able to have % on either side of the search word, and I can't seem to do that with '%:searchterm%', it just gives an error of ORA-01036: illegal variable name/number.
Can I parameterize but still have my flexible like statement be a part of it?
Instead of doing the concatenation in your VB code, do the concatenation in the SQL statement. Then what you're trying to do should work. Here's some SQL illustrating what I'm talking about:
select ID_ELEMENT, ELEMENT_NAME
from table_of_elements
where upper(ELEMENT_NAME) like ('%' || upper(:searchterm) || '%')
BTW, you might end up with more efficient queries if you switch the collation on ELEMENT_NAME to case-insensitive and then remove the calls to upper().
Since you're using oracle, another option would be to use Oracle Text to perform the search.
It can take a bit to set up properly, but if you have a large amount of text to search, or have some sort of structured data, it can offer you many more options than a simple wild-card comparison.
It also has some nice features for dealing with multiple languages, if you happen to have that problem as well.