SQL select return value to variable - asp.net

working with: ASP.net using VB.net connecting to MS SQL Server
What I'm trying to do is take the result of a SQL select query and place that in a string variable so it can be used in things like a textbox or label. code so far that doesn't work...
Imports System.Data.SqlClient
Partial Class dev_Default
Inherits System.Web.UI.Page
Protected Sub form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles form1.Load
Dim cnPodaci As New SqlConnection
cnPodaci.ConnectionString = "Data Source=<server>;Initial Catalog=<DB>;User ID=<UserName>;Password=<Password>"
cnPodaci.Open()
Dim cm As New SqlCommand
cm.CommandText = "SELECT * FROM tbl1"
cm.Connection = cnPodaci
Dim dr As SqlDataReader
dr = cm.ExecuteReader
TextBox1.Text = dr.GetString(0)
cnPodaci.Close()
End Sub
End Class

Although you have executed the query by calling "ExecuteReader" on the command, what is actually returned is an object (a DataReader) that will allow you to iterate over any query results. To do this you must call the "Read" method on the DataReader (this could be called multiple times in the clause of a "while" loop). Modifying your code to something like this should work:
If dr.Read() Then
TextBox1.Text = dr.GetString(0)
End If
However, bear in mind that this will only work if the first field returned by your query is a string, otherwise a cast exception may be thrown.

If the query is supposed to return a single value, you can simply use the ExecuteScalar method:
TextBox1.Text = DirectCast(cm.ExecuteScalar(), String)

The problem is that SELECT queries will return a dataset, or at least a row from a dataset, not a string.
Do you absolutely need the entire result set as a string? Or can what you're trying to do be achieved by referencing a point in an array or dataset?

Related

I want to update a GridView based off of a value selected from a DropDownList by editing my SqlDataSource

I'm trying to accomplish this by updating the SelectCommand on my SqlDataSource, clearing the GridView, and then reapplying the GridView.DataBind() based off the value in the dropdown. It's not working, and honestly, I'm totally new to this, so I very well could just be doing things incorrectly. Here's some sample code that gives an idea of what I've got:
Protected Sub drp_product_SelectedIndexChanged(sender As Object, e As EventArgs) Handles drp_product.SelectedIndexChanged
grd_ingredientview.DataSource = Nothing
grd_ingredientview.DataBind()
SqlDataSource1.SelectCommand = "blah blah sample select command" + drp_product.SelectedValue
grd_ingredientview.DataSource = SqlDataSource1
grd_ingredientview.DataBind()
End Sub
Again, this doesn't work, and throws up an error, saying: Both DataSource and DataSourceID are defined on 'grd_ingredientview'. Remove one definition.
Any help with this would be appreciated, along with a description for why this isn't working and how your suggestion does. Still learning a lot of this. Thank you!
Well, use code to load up the grid view in the first place, and you can dump the the datasoruce1. (just remove it from the web form). (but ANSWER NO to re-create the fields an update the grid view if prompted).
So yes, use the wizard, let it create that data source. Choose your columns. Test the grid. Ok, now it works. Now that the grid been built?
then delete the Datasourc1 from the page. And then for the property sheet, remove the datasource setting. This one:
So, now we removed that Datasource1 object from the page, and the setting that points to that datasource.
And do the SAME idea with the combo box. Use the wizard, even let it build + add a data source for the combo box. And again, delete the data source and again remove the datasource setting for the combo box just like we did for the gird.
So, now we can (and will) freely use code to fill out the data grid.
So, on page load, the one time (first time) data load, we can do this:
If IsPostBack = False Then
' first time page load - display the grid.
Call LoadGrid("")
Call LoadCombobox
End If
And note, for the combo box? Again, you can freely use the wizards to setup the combo box, but AGAIN remove that data source setting like we did for the grid.
So, now all our code looks like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
' first time page load - display the grid.
Call LoadGrid("")
Call LoadCombobox
End If
End Sub
Sub LoadGrid(Optional strWhere As String = "")
Dim strSQL As String = "SELECT * from tblHotels "
If strWhere <> "" Then
strSQL += " WHERE " & strWhere
End If
Me.GridView1.DataSource = Myrst(strSQL)
Me.GridView1.DataBind()
End Sub
Sub LoadComboBox()
Dim strSQL As String = "SELECT City from tblHotels GROUP BY City"
Me.DropDownList1.DataSource = Myrst(strSQL)
Me.DropDownList1.DataBind()
End Sub
Protected Sub DropDownList1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles DropDownList1.SelectedIndexChanged
Dim strWhere As String
strWhere = "City = '" & DropDownList1.SelectedValue & "'"
Call LoadGrid(strWhere)
End Sub
Now the only part I left out was MyRst(). It simply returns a datatable. So, you can use that code (and place it outside in a standard code module.
That way you can use it over and over though out your application, and not have to create a connect object and sql command over and over until you go nuts.
It also means you only EVER use/get/grab a connection string in ONE place in your code, so it is easy to change it when you change the database.
So the handy dandy routine that saves you having over and over to re-write query code and the connection object is this:
Public Function Myrst(strSQL As String, Optional strCon As String = "") As DataTable
' this also allows one to pass custom connection string -
' if not passed, then default
If strCon = "" Then
strCon = My.Settings.TestDatabase3
End If
Using mycon As New SqlConnection(strCon)
Dim oReader As New SqlDataAdapter
Dim rstData As New DataSet
oReader.SelectCommand = New SqlCommand(strSQL, mycon)
Try
oReader.Fill(rstData)
Return rstData.Tables(0)
Catch
Return Nothing
End Try
End Using
End Function
So, with the above simple helper routine, then the code is very easy to write. In fact I find its less code then even desktop code or even writing code in MS-Access.
so the above simple example would select a city from the combo box, and then filter/set the gride to only display that city.
And if you want, you don't have to fill the grid on page load, since the user is about to select a combo box value. So, just comment out the LoadGrid on page load, and only call it when you make a combo (dropdownlist) selection.
As noted, don't forget to set the dropdown list auto-post back = true.
All in all? The above is not a lot of code, and is no more then say doing this for the desktop, or even doing this in Access.

ASP.NET page getting Timeout expired requiring the application pool being recycled every hour

My new application page is getting a timeout error every hour or so after getting some traffic on the page, and by traffic I mean users submitting 5-10 applications. How do I find the cause of the connections getting tied up?
This has been an issue in the past so whenever I use a sql data reader object I make sure to implement the "Using" statement. I've also made sure that the thread isn't aborted before the data reader is disposed of. I doubt that my use of data readers is the issue, so maybe it's my non-query code that's causing the issue, but I can't see why.
I also use a few sqldatasource objects for my dropdownlist controls, and as far as I know it wouldn't be the source of my issue.
See code example for how I use my sql objects.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Using drApp As SqlDataReader = LookupAppByID()
'some code
drApp.Close()
End Using
End Sub
Public Function LookupAppByID() As SqlDataReader
Dim Command As New SqlClient.SqlCommand
Command.Connection = GetDBConnection()
Command.CommandType = CommandType.Text
Command.CommandText = "select statement"
Return Command.ExecuteReader(CommandBehavior.CloseConnection)
End Function
Public Function UpdateAppStatus() As Integer
UpdateAppStatus = 0
Using Command As New SqlClient.SqlCommand("update statement", GetDBConnection())
UpdateAppStatus = Command.ExecuteNonQuery()
Command.Connection.Close()
Command.Connection.Dispose()
Command.Dispose()
End Using
End Function
Public Function GetDBConnection() As SqlClient.SqlConnection
Dim connection As New SqlClient.SqlConnection
connection.ConnectionString = "connection string"
connection.Open()
Return connection
End Function
Obviously I expect it to chug along without a hitch but when users start hitting the page it gets this error: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Is there a problem with my code?
How can I narrow down what is causing this issue?
I would keep the database objects local so I can ensure that they are closed and disposed. Create and dispose within one method. I created a class so you can easily pass all its properties in a single variable.
'User Interface Code
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim id As Integer 'No sure where the value comes from
Using dtApp As DataTable = DataAccess.LookupAppByID(id)
'some code
End Using
End Sub
Protected Sub Update_Click(sender As Object, e As EventArgs) Handles Update.Click
Dim Applic As New ApplicationData()
Applic.ApplicantsName = txtName.Text
Applic.ID = CInt(txtID.Tex)
Applic.ApplicationStatus = "Approved"
Dim retVal = DataAccess.UpdateAppStatus(Applic)
If retVal = 1 Then
'Alert user of success
Else
'Alert user of failure
End If
End Sub
Public Class ApplicationData
Public Property ID As Integer
Public Property AppDate As Date
Public Property ApplicantsName As String
Public Property ApplicationStatus As String
End Class
Public Class DataAccess
Private Shared ConString As String = "Your connection string"
Public Shared Function LookupAppByID(AppID As Integer) As DataTable
Dim dt As New DataTable
Using cn As New SqlConnection(ConString)
Using Command As New SqlCommand("select * From YourTable Where ID = #ID", cn)
Command.Parameters.Add("#ID", SqlDbType.Int).Value = AppID
cn.Open()
dt.Load(Command.ExecuteReader)
End Using
End Using
Return dt
End Function
Public Shared Function UpdateAppStatus(App As ApplicationData) As Integer
Dim AppStatus = 0
Using cn As New SqlConnection(ConString)
Using Command As New SqlClient.SqlCommand("Update YourTable Set Status = #Status Where ID = #ID;", cn)
Command.Parameters.Add("#Status", SqlDbType.VarChar, 50).Value = App.ApplicationStatus
Command.Parameters.Add("#ID", SqlDbType.Int).Value = App.ID
cn.Open()
AppStatus = Command.ExecuteNonQuery()
End Using
End Using
Return AppStatus
End Function
End Class

Decoding Encrypted Query string

I am using the method described in the following LINK and I am using the following code to encrypt:
'Page1.aspx
Protected Sub butEncrypt_Click(sender As Object, e As EventArgs) Handles butEncrypt.Click
Dim QueryString As String = "type=Int&pk=" & _primaryKey
QueryString = Tools.encryptQueryString(QueryString)
Response.Redirect(/SearchResults.aspx?Val=" & QueryString)
End Sub
and then finally de-encrypt:
'SearchResults.aspx
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If (Not IsPostBack) Then
If Not String.IsNullOrEmpty(HttpContext.Current.Request(CIAppGlobals.GlobalVar.Val)) Then
Dim qs As String = Request.QueryString(CIAppGlobals.GlobalVar.Val)
qs = Tools.decryptQueryString(qs)
Dim Values As String() = qs.Split(CChar("&"))
_imageType = String.Empty
_primaryKey = 0
For Each value As String In Values
Dim data As String() = value.Split(CChar("="))
Select Case data(0).ToUpper
Case "TYPE"
_imageType = data(1)
Case "PK"
_primaryKey = CInt(data(1))
End Select
Next
Else
_imageType = HttpContext.Current.Request("type")
_primaryKey = CInt(HttpContext.Current.Request("pk"))
End If
End If
End Sub
My question is should I being using a different method to extract the decoded query string values other than what I am doing? Thanks in advance for your constructive responses.
Solution
After looking at Darin's response I have decided to incorporate it into my project, here is my updated code:
'Page1.aspx
Protected Sub butEncrypt_Click(sender As Object, e As EventArgs) Handles butEncrypt.Click
Dim query = HttpUtility.ParseQueryString(String.Empty)
query("type") = "Int"
query("pk") = CStr(_primaryKey)
Dim QueryString As String = Tools.encryptQueryString(query.ToString())
Response.Redirect(/SearchResults.aspx?Val=" & QueryString)
End Sub
I still want to encrypt the query string because I want to prevent users from changing the Query String Values manually
You are incorrectly building the query string in the first place. You are using string concatenations and not properly encoding them. What if _primaryKey contains a & or = characters? You could use the ParseQueryString method to properly build a query string:
Dim query = HttpUtility.ParseQueryString(String.Empty)
query("type") = "Int"
query("pk") = _primaryKey
Dim queryString = query.ToString()
The same method could be used for parsing the decoded query string:
Dim values = HttpUtility.ParseQueryString(qs)
Dim type = query("type")
Dim primaryKey = query("pk")
' work with the type and primaryKey values
Never use string concatenations and splitting when dealing with urls. Always use the right tool for the right job.
That's as far as creating/parsing query strings is concerned. As far as encrypting/decryption the values is concerned, you haven't shown/told us anything about the Tools class that you are using so I cannot provide you with any constructive comments about it.
You know that the best encryption is to never send the actual value to the client. So you could store it in some backend storage on the server and then use an unique id in the url. This id could be used on the target page to fetch the original value. This way you don't need to be encrypting/decrypting anything.

How to display whole records from database in Gridview and also do filteration using textbox?

How to display whole records from database in Gridview and also do filteration using textbox ?
There are any number of ways to do this, and which way you approach the probelm might depend on a number of inter-related factors; How many records will reasonable be returned each time a user perfroms a search? Should the list by default load with ALL records, and only filter upon request, or should it load emply, and only return requested records? Under reasonable use conditions, will the DGV be loaded with the entire table contents, or only a few records, post-search?
These and other considerations may or may not impact how you decide to fill and perform your filtering operation.
THIS example is a pretty rudimentary approach, and does not employ some of the ADO.NET niceties such as DataSet, TableADapter, and such. Instead it performs the filtering as a beck-end operation, submitting a parameterized query and returning the result set as a DataTable, which can then be set directly as the data source for your DGV control. I will not be suprized if this opens an argument (i mean, debate) about the ways and means of retreiving data with ADO.NET . . .
Anyway, there are other options, and I cannot be certain what will be most practical and/or efficient, given my limited knowledge of your design. One example would be to retreive a fully populated DataTable as a Private Class Memeber of the form, and then perform DataView.RowFilter operations against it, using the output as the DataSource for your Grid. THis has pros and cons as well; primarily, it might be better for limited-size result sets, or for cases in which data Access against the back-end suffers performance bottlenecks.
A fianl note - my silly example here essentially refines the search each time the text in the Textbox changes. Depending upon your needs, you may want to set it up so that the search is not executed until the user presses a button, or the enter key.
NOTE: THis is just one example, and any code like this should be refined with exception handling, and adapted for the performance requirements of your design!
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim dgv As DataGridView = Me.DataGridView1
Me.UpdateSearch("")
End Sub
'A Function which returns a DataTable, to be used as the DataSource for a DataGridView:
Private Function ClientsDataTable(ByVal SearchCriteria As String) As DataTable
'The default popoulation of your Grid Control will determine how you
'contruct your SQL and/or set up you parameter(s); If you want it BLANK until the user enters a value in
'your textbox, you will need to modify some of the logic here . . . THIS extra-simple example
'fills the DGV with ALL records in the table if no parameter (and empty String) is passed:
Dim SQL As String = _
"SELECT ClientID, LastName, FirstName " & _
"FROM tblClient " & _
"WHERE LastName Like #LastName & '%'"
Dim dt As New DataTable
Using cn As New OleDb.OleDbConnection(My.Settings.CreateThisConnection)
Using cmd As New OleDb.OleDbCommand(SQL, cn)
cmd.Parameters.AddWithValue("#LastName", SearchCriteria)
cn.Open()
Dim dr As OleDbDataReader = cmd.ExecuteReader
dt.Load(dr)
dr.Close()
cn.Close()
End Using
End Using
Return dt
End Function
Private Sub TextBox1_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Me.UpdateSearch(Me.TextBox1.Text.Trim)
End Sub
Private Sub UpdateSearch(ByVal SearchCriteria As String)
Me.DataGridView1.DataSource = ClientsDataTable(SearchCriteria)
End Sub
End Class

How to get work ASP.NET DataSet when connection losts?

I made a basic program that connects and gets content from a table via SQL, it's working normally. What I want is; when connection losts via SQL Server or internet connection, it must continue to list items that it got before connection losts instead of giving "Connection Problem Error".
Code is like this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strSQL As String
Dim conn As New SqlConnection
conn.ConnectionString = baglan()
conn.Open()
strSQL = "SELECT * FROM Telefon_Otomasyon"
Dim da As New SqlDataAdapter(strSQL, conn)
Dim dset As New DataSet()
da.Fill(dset, "Telefon_Otomasyon")
Dim Hepsi As DataRow
For Each Hepsi In dset.Tables("Telefon_Otomasyon").Rows
Response.Write(Hepsi("Arayan") & "<br />")
Next
End Sub
Thanks!
What you can do is store your dataset in Session: (excuse my VB, i'm very rusty with it)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim strSQL As String
Dim conn As New SqlConnection
conn.ConnectionString = baglan()
conn.Open()
strSQL = "SELECT * FROM Telefon_Otomasyon"
Dim da As New SqlDataAdapter(strSQL, conn)
Dim dset As New DataSet()
Try
da.Fill(dset, "Telefon_Otomasyon")
MyDataset = dset
Catch ex As SqlException
dset = MyDataset
End Try
Dim Hepsi As DataRow
For Each Hepsi In dset.Tables("Telefon_Otomasyon").Rows
Response.Write(Hepsi("Arayan") & "<br />")
Next
End Sub
Private Property MyDataset() As DataSet
Get
return Session("myDataset")
End Get
Set(ByVal value as DataSet)
Session("myDataset") = value
End Set
End Property
This is also a very basic example, it needs to be tidied up before you can use it in production code, i.e. you need to consider what to do if there is no dataset stored in Session (if it returns null). You may want to be a bit smarter than that and just store a specific table. Note that Session can expire though, so do some reading on it. This should be enough to steer you in the right direction.
Further note: if you want something a little less volatile than Session then you could try using the Cache instead.
I'm not sure I understand the problem here. While I'm not a VB-programmer it seems to me like once the page loads it will run the SQL query and then process that dataset.
If you reload the page and the SQL connection isn't working you will get an error that you'd need to handle somehow (not sure how VB exceptions work but I'm sure you can figure that out).
If you on the other hand mean that you want to get whatever data you can from a query that gets disconnected mid-query - I'd say that is pretty hard and only relevant for huge queries.

Resources