Click here to Skip to main content
16,020,313 members
Articles / Web Development / ASP.NET
Article

Using SQLDataReader and SQLDataAdapter

Rate me:
Please Sign up or sign in to vote.
3.25/5 (12 votes)
19 Mar 20063 min read 144.8K   769   24   7
retrieve

Sample Image - RetrieveMoreData.gif

Introduction

    The useability and the interaction for the end users with your web form will reflect the term of the success and the completeness for your work,and especially if most of your web forms get and show data from database. we talk to database via a connection ,so your connection will be in the lightweight and have a short time and this dedicated in using SqlDataReader class and your connection will be more efficient in using SQLDataAdapter class.

Background (optional)

DataReader and DataAdapter are both objects of ADO.Net,which enable you to access your database.DataReader is a storage object which dedicated for read only,it has a collection of methods that support SqlDataReader like ExecuteReader which move the command text to the connection instead of using SqlDataAdapter.
Besides that we can use SqlDataAdapter class for read and write data from and to database,i represent SqlDataAdapter like the taxi which reach people from one place to another and come back.SqlDataAdapter do the same but it hold Query statement(select statement)and it will come back to fill data in DataSet or non Query statements (insert,delete and update)and it will come back with the number of the affected rows.

 

Using the code

     i had created a computer database called library using SQL Server and a table called Books and i have three fields :
1.ISBN
2.Book Title
3.Book Category

    i have a dropdownlist and set AutoPostBack property to True,for display more details about the selected ISBN i have three TextBoxes the first is to display the selected ISBN ,the second TextBox for display the Book Title and the third to display the Book Category. then i retrieve the data and put it in TextBoxes ,i had choosen TextBoxes better than Labels to display data ,i made a right click on each TextBox then set the ReadOnly property to True and this nice thing to have.
i call System.Data.SqlClient Namespace to define what i need in this example for my connection requirements.

    Imports System.Data.SqlClient
Public Class RetrieveMoreData
    Inherits System.Web.UI.Page
//...    
    Dim channel As New SqlConnection
    Dim dataquery As New SqlCommand
    Dim dataholder As New SqlDataAdapter
    Dim ds As New DataSet
    Dim datareader As SqlDataReader
    Dim dv As New DataView   

on the page load i called GetChannel function which satisfy the connection Requirements and FillDdl function which fill the dropdownlist.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'Put user code to initialize the page here
    Try
        If Not IsPostBack Then
            GetChannel()
            FillDdl()
        End If
    Catch ex As Exception
        Response.Write("an error occured")
    End Try
End Sub

in GetChannel function you can satisfy your ConnectionString.

Private Sub GetChannel()
     Try
         channel.ConnectionString = "workstation id=COMPUTER NAME;packet size=4096;user id=SQL SERVER USER ID;_
         integrated security=SSPI;data source=COMPUTER NAME;persist security info=False;initial catalog=DATABASE NAME"
     Catch ex As Exception
         Response.Write("an error occured")
     End Try
 End Sub

In FillDdl function i opened the connection and moved the CommandText to the connection by datareader instead of SqlDataAdapter,IsDBNull is a function returns True if no available data and returns False if data is available,in case IsDBNull is False datareader get the value,after that i add it to the dropdownlist

<PRE> Private Sub FillDdl()
        Try
            channel.Open()
            dataquery.CommandText = "select * from Books"
            dataquery.Connection = channel
            datareader = dataquery.ExecuteReader   //datareader Read One Row at a time
            ddlGetISBN.Items.Add("Select ISBN")     //add a default item in dropdownlist
            While datareader.Read            //datareader enter in a loop while the data is available 
                If Not datareader.IsDBNull(0) Then
                    ddlGetISBN.Items.Add(datareader.GetValue(0).ToString)
                End If
            End While
            channel.Close()
        Catch ex As Exception
            Response.Write("an error occured")
        End Try
    End Sub

i used SqlDataAdapter here to move the command text to the connection,after that i had filled the retrieving data in the dataset,i tooke a custom view for the DataSet then filter it by dv with isbn variable which selected from the dropdownlist after that i convert it to ToInt64 (64-bit signed integer) because ISBN consist of 10 digits,then i filled the TextBoxes whith the particular data,i call ShowDetails function on the SelectedIndexChanged event for the dropdownlist.

//..
    Private Sub ShowDetails()
        Try
            GetChannel()
            channel.Open()
            dataquery.CommandText = "select * from Books"
            dataquery.Connection = channel
            dataholder.SelectCommand = dataquery
            dataholder.Fill(ds, ("Books"))
            dv.Table = ds.Tables("Books")     //take a custom view for Books Table from the DataSet
            dv.RowFilter = "isbn=" & System.Convert.ToInt64(ddlGetISBN.SelectedItem.Text)
            txtISBN.Text = dv(0)("ISBN")
            txtBookTitle.Text = dv(0)("Book Title")
            txtBookCategory.Text = dv(0)("Book Category")
            channel.close()           
        Catch ex As Exception 
            Response.Write("an error occured")       
        End Try       
    End Sub

here i call ShowDetails function and after the process finished i clear the selection by ClearSelection method in the dropdownlist and it doesn't useful in this case but if you have a user control and you want to manipulate it from dropdownlist selection,too you want to repeat the same selection twice or more you can use ClearSelection method as the best solution for the mentioned cases.

Private Sub ddlGetISBN_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles ddlGetISBN.SelectedIndexChanged
     Try
         ShowDetails()
         ddlGetISBN.ClearSelection()
     Catch ex As Exception
         Response.Write("an error occured")
     End Try
 End Sub

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Technical Lead BEAT
Jordan Jordan
Iyad Abu Abdu is currently a technical team leader at Blue Energy for Advanced Technologies (Jordan),he works in architecting and planning for enterprise solutions using different entities such as MOSS 2007, K2 blackPearl, .Net and MS SQL Server.

To contact Iyad,email him at iyad.abuabdu@gmail.com

Comments and Discussions

 
GeneralADO Connection String Pin
VenkateshSaNaTa17-Apr-08 22:06
professionalVenkateshSaNaTa17-Apr-08 22:06 
GeneralSome Thoughts Pin
renzea22-Mar-06 10:03
renzea22-Mar-06 10:03 
Some thoughts I had while reading the article:

1) Why make the data access objects object scope variables? The page is reconstructed on the server for every page load and postback (unless the page is cached) so placing the variables any where other than where they are used just makes the code harder to read.

2) There is no reason to surround the ConnectionString property with a try catch block. You are setting a string property. The connection throws the exception on the open method. I have never personally seen ConnectionString throw an exception.

3) The connection string should be stored in the ConnectionStrings section of the web.config file. Failing that, save it as a global variable or function.

4) There is no reason to loop through the results of the data reader to fill the drop down list. You can do the same thing with the following code:

ddlGetISBN.DataSource = datareader<br />
ddlGetISBN.DataBind()<br />
ddlGetISBN.Items.Insert(0, "Select ISBN")


The benefit of doing this is if you later change your data source to a DataSet, business object, or whatever, the code will still function. You just have to set the DataTextField and DataValueField of the Drop Down Data list.

5) From a useability standpoint, the text boxes are confusing. I was trying to figure out for several minutes how the user was supposed to execute the query. It took me a little while to understand they are used only for output.

So, you should probably use labels. They are read-only and are less apt to befuddle the user.

Actually, it would probably be better to replace the ISBN drop down box with a command button, and then allow the user to search for the information based on their own criteria.

For example:

if (txtISBN.Text.Lenght > 0) then<br />
    dataquery.CommandText = "SELECT * FROM Books WHERE ISBN = @Param1"<br />
    dataquery.Parameters.AddWithValue("@Param1", txtISBN.Text)<br />
else<br />
    if (txtBookTitle.Text.Length > 0) then<br />
        if (txtBookCategory.Text.Length > 0) then<br />
            dataquery.CommandText = "SELECT * FROM Books WHERE ([Book Title] = @Param1) AND ([Book Category] = @Param2)"<br />
            dataquery.Parameters.AddWithValue("@Param1", txtBookTitle.Text)<br />
            dataquery.Parameters.AddWithValue("@Param2", txtBookCategory.Text)<br />
        else<br />
            dataquery.CommandText = "SELECT * FROM Books WHERE [Book Title] = @Param1"<br />
            dataquery.Parameters.AddWithValue("@Param1", txtBookTitle.Text)<br />
        end if<br />
    else<br />
        if (txtBookCategory.Text.Length > 0) then<br />
            dataquery.CommandText = "SELECT * FROM Books WHERE [Book Category] = @Param1"<br />
            dataquery.Parameters.AddWithValue("@Param1", txtBookCategory.Text)<br />
        else<br />
            ' No query provided; do whatever you want to here<br />
        end if<br />
    end if<br />
end if


Then display the results in a repeater, data grid, or something similar.

The reason for this is that A) There are millions of books. Binding ISBNs to a drop down box is unrealistic, unless you are dealing with an extremely small subset of them. B) Users may want to find books by some criteria other than the ISBN. What if they don't know the ISBN? I am more likely to know the title of a book (i.e. The Cat in the Hat) as opposed to the ISBN (i.e. 039480001X, for the same book).

Also, the ISBN is not guaranteed to be numeric, any more than a Vehicle Identification Number is. See the afore mentioned ISBN for the perfect example. It contains an X.

6) If you do intend to just fetch one item from the database at a time, and you aren't using binding, you would be better off using output parameters. For example:

dataquery.CommandText = "SELECT @ISBN=ISBN, @BookTitle=[Book Title], @BookCategory=[Book Category] FROM Books WHERE ISBN=[@Param1]"<br />
dataquery.Parameters.Add("@ISBN", SqlDbType.VarChar, 15, "ISBN").Direction = ParameterDirection.Output<br />
dataquery.Parameters.Add("@BookTitle", SqlDbType.VarChar, 15, "[Book Title]").Direction = ParameterDirection.Output<br />
dataquery.Parameters.Add("@BookCategory", SqlDbType.VarChar, 15, "[Book Category]").Direction = ParameterDirection.Output<br />
dataquery.Parameters.AddWithValue("@Param1", txtISBN.Text)


Then open the connection, and execute a non-query command. Then to get the values, simply access the parameters collection.

txtISBN.Text = dataquery.Parameters(0).Value.ToString()<br />
txtBookTitle.Text = dataquery.Parameters(1).Value.ToString()<br />
txtBookCategory.Text = dataquery.Parameters(2).Value.ToString()


(Note: Using ToString() helps protect against null values. Also, I set the varchar lengths to 15 because I am not sure what the actual size is of your text fields.)

Doing it that way, you aren't stuffing all the information into a datatable first. If you need disconnected data (i.e. to modify on the business tier before returning it to the presentation layer), consider the following:

dim Table as new DataTable<br />
Table.Load(dataquery.ExecuteReader())


Same accessibility, half the objects. Just be sure to close the connection when you are done with it, preferably in a Finally block.

Finally, as a matter of best practices, you should not use spaces in column names. You can't access those columns via SQL without first enclosing them in brackets.
GeneralRe: Some Thoughts Pin
AnasHashki22-Mar-06 21:02
AnasHashki22-Mar-06 21:02 
GeneralRe: Some Thoughts Pin
Iyad Abu Abdu22-Mar-06 22:09
Iyad Abu Abdu22-Mar-06 22:09 
GeneralRe: Some Thoughts Pin
renzea23-Mar-06 9:09
renzea23-Mar-06 9:09 
GeneralRe: Some Thoughts Pin
Darth Jackass12-May-06 4:15
Darth Jackass12-May-06 4:15 
Generalgood Pin
yazan_nemer4-Mar-06 20:41
yazan_nemer4-Mar-06 20:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.