65.9K
CodeProject is changing. Read more.
Home

Using Data Classes in ASP.NET - A Beginner's Guide

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Aug 16, 2015

CPOL

3 min read

viewsIcon

11952

downloadIcon

35

A beginner's introduction to using data classes in ASP.NET.

Introduction

This is a beginner's introduction to using data classes in ASP.NET. I have tried to keep it as simple as possible while introducing the concepts. To that end, there is neither client-side nor server-side input validation for example, I have just concentrated on relevant code to the subject. I have written it in VB.NET because I think novices will find it easier to translate from that to C#.NET than the other way round, should they need to. The sample web application project attached, built in Visual Studio 2008, references a SQLite database, as this only requires a reference to System.Data.SQLite.dll, but of course can easily be adapted for any other.

Background

Why Use Data Classes - Why this Article?

It pains me to see code where a datagrid, for example, is bound to a database and columns are bound using something like:

<%# Container.DataItem("columnName") %>

Apart from anything else, this is prone to typo errors, and is anyway time-consuming to type. A major advantage of using classes is that intellisense kicks in, and does half your work for you. (Assuming you’re using an IDE that supports Intellisense, that is.) And your code will be cleaner and much easier to read, and maintain. Once you get to grips with them (and they aren’t hard), you will find your productivity will rocket, and coding (even more) enjoyable. I’ve never found overly verbose explanations too much help – far better, in my experience, to see some code.

To work then...

Using the Code

The sample project manages the names and dates of birth of ... some group.  So we’ll start with a simple database structure:

Table name:   tblPeople
Columns:
ID  (integer, autoincrement)
sFirstName (text)
sLastName (text)
dDOB (date, possibly NULL if not known.)

(It's a good idea to prefix field names with something that indicates their type – e.g. ‘s’ for a String, ‘i’ for an Integer, etc.)
The sample project will create this when first run, and populate it with a few rows.

So that’s our database. Now, in our project, we declare a class reflecting this database table structure: (see classes.vb in the download project.)

Friend Class clsPeople

   Private _ID As Integer
   Public Property ID() As Integer
      Set(ByVal value As Integer)
         _ID = value
      End Set
      Get
         Return _ID
      End Get
   End Property

   Private _sLastName As String
   Public Property sLastName() As String
      Set(ByVal value As String)
         _sLastName = value
      End Set
      Get
         Return _sLastName
      End Get
   End Property

   Private _sFirstName As String
   Public Property sFirstName() As String
      Set(ByVal value As String)
         _sFirstName = value
      End Set
      Get
         Return _sFirstName
      End Get
   End Property

   Private _dDOB As Nullable(Of Date)
   Public Property dDOB() As Nullable(Of Date)
      Set(ByVal value As Nullable(Of Date))
         _dDOB = value
      End Set
      Get
         Return _dDOB
      End Get
   End Property

   Public Sub New()
      _ID = 0
      _sLastName = ""
      _sFirstName = ""
      _dDOB = Nothing
   End Sub

This defines our class structure, in which we can store (Set) and retrieve (Get) data records.
If we now want to retrieve all the records in our database and display them in a datagrid, we can use the following method: (see adp.vb)

   Friend Function collPeople() As Collection
      Dim coll As New Collection
      Dim cls As clsPeople
      Dim objCmd As New SQLiteCommand
      Dim objReader As SQLiteDataReader
      Try
         openDbConn()
         objCmd.Connection = dbCon.thisConn
         objCmd.CommandText = "select ID,sLastName,sFirstName,dDOB from tblPeople order by sLastName"
         objReader = objCmd.ExecuteReader
         If objReader.HasRows Then
            Do While objReader.Read
               cls = New clsPeople
               cls.ID = objReader.GetInt32(0)
               cls.sLastName = objReader.GetString(1)
               cls.sFirstName = objReader.GetString(2)
               If Not IsDBNull(objReader.GetValue(3)) Then cls.dDOB = CDate(objReader.GetValue(3))
               coll.Add(cls)
            Loop
         End If
         objReader.Close()
         closeDbConn()
         Return coll
      Catch ex As Exception
         closeDbConn()
         WriteLog("colPeople", ex.Message)
         Return Nothing
      End Try
   End Function

This function returns a collection of our class objects, each one set to a record in the database.

Now, we bind this in our web form like so:

On the HTML page (default.aspx):

       <asp:DataGrid runat="server" ID="dgX" DataKeyField="ID" AutoGenerateColumns="false" ShowFooter="true" AllowPaging="true" PageSize="10">
           <PagerStyle Mode="NumericPages" Position="TopAndBottom" />
           <HeaderStyle BackColor="#e0e0e0" />
           <FooterStyle BackColor="#f0f0f0" />
           <Columns>
                <asp:BoundColumn DataField="ID" Visible="False" ReadOnly="true"></asp:BoundColumn>
                <asp:TemplateColumn HeaderText="Name" ItemStyle-Width="400px">
                    <ItemTemplate><asp:Literal runat="server" ID="sName"></asp:Literal></ItemTemplate>
                    <EditItemTemplate>
                       <asp:TextBox runat="server" ID="sLastName" _
                       Width="190px" MaxLength="50"></asp:TextBox>
                       <asp:TextBox runat="server" ID="sFisrtName" _
                       Width="190px" MaxLength="50"></asp:TextBox>
                    </EditItemTemplate>
                    <FooterTemplate>
                       <asp:TextBox runat="server" ID="sLastName" _
                       Width="190px" MaxLength="50" _
                       Text="(Last name)"></asp:TextBox>
                       <asp:TextBox runat="server" ID="sFisrtName" _
                       Width="190px" MaxLength="50" _
                       Text="(First name)"></asp:TextBox>
                   </FooterTemplate>
                </asp:TemplateColumn>
                <asp:TemplateColumn HeaderText="D.O.B." _
                ItemStyle-Width="120px">
                    <ItemTemplate><asp:Literal runat="server" _
                    ID="sDOB"></asp:Literal></ItemTemplate>
                    <EditItemTemplate><asp:TextBox runat="server" _
                    ID="sDOB" Width="110px" _
                    MaxLength="11"></asp:TextBox></EditItemTemplate>
                    <FooterTemplate><asp:TextBox runat="server" _
                    ID="sDOB" Width="110px" _
                    MaxLength="11"></asp:TextBox></FooterTemplate>
                </asp:TemplateColumn>
                <asp:EditCommandColumn ButtonType="LinkButton" _
                CancelText="cancel" EditText="edit" _
                UpdateText="update" ItemStyle-Width="120px" _
                ItemStyle-HorizontalAlign="Center"></asp:EditCommandColumn>
                <asp:TemplateColumn ItemStyle-Width="50px" _
                ItemStyle-HorizontalAlign="Right">
                    <ItemTemplate><asp:LinkButton runat="server" _
                    ID="lbDelete" CommandName="delete" _
                    Text="delete"></asp:LinkButton></ItemTemplate>
                    <FooterTemplate><asp:LinkButton runat="server" _
                    ID="lbAdd" CommandName="insert" _
                    Text=" add"></asp:LinkButton></FooterTemplate>
                </asp:TemplateColumn>               
           </Columns>
        </asp:DataGrid>

Of course, we could use bound columns for all the bindings, but I want to show the usefulness of data classes in the code behind...

In the code behind, we simply bind our collection to the database:

      Dim coll As Collection = adp.collPeople()
      If Not coll Is Nothing Then
         dgX.DataSource = coll
         dgX.DataBind()
         dgX.PagerStyle.Visible = CBool(coll.Count > dgX.PageSize)
      End If

And in the ItemDataBound event:

Private Sub dgX_ItemDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgX.ItemDataBound
      Select Case e.Item.ItemType
         Case ListItemType.AlternatingItem, ListItemType.Item
             ' display record according to requirements
            Dim cls As clsPeople = CType(e.Item.DataItem, clsPeople)
            Dim sName As Literal = CType(e.Item.FindControl("sName"), Literal)
            Dim sDOB As Literal = CType(e.Item.FindControl("sDOB"), Literal)
            Dim btnDel As LinkButton = e.Item.Cells(4).Controls(0)
            sName.Text = cls.sLastName.ToUpper & ", " & cls.sFirstName
            If cls.dDOB Is Nothing Then
               sDOB.Text = "(unknown)"
            Else
               sDOB.Text = String.Format("{0:dd-MMM-yyyy}", CDate(cls.dDOB))
            End If
            btnDel.Attributes.Add("onclick", "return confirm('Are you sure you want to delete this item?')")
         Case ListItemType.EditItem
            ' code in download
         Case ListItemType.Footer
            ' code in download
        Case Else
            '
      End Select
   End Sub

In such a simple example as this, there may not seem much advantage to using data classes, but imagine a more complex data structure, and a more complex UI requirement, and you can quickly see how writing this binding code becomes much easier – bear in mind that Visual Studio’s intellisense will recognise your data class, and as soon as you type...

cls.

... you will be presented with a list of all the class properties.

Similarly, when adding or updating records, we simply declare a new clsPeople and set the class properties accordingly (equal to the value of text boxes on our form, for example) and then pass this class to an add or update function: e.g.:

   Friend Function AddPeople(ByVal cls As clsPeople) As Integer
      Dim objCmd As New SQLiteCommand
      Try
         openDbConn()
         objCmd.Connection = dbCon.thisConn
         objCmd.CommandText = "insert into tblPeople (sLastName,sFirstName,dDOB) values (?,?,?)"
         objCmd.Parameters.AddWithValue("@sLastName", cls.sLastName)
         objCmd.Parameters.AddWithValue("@sFirstName", cls.sFirstName)
         If cls.dDOB Is Nothing Then
            objCmd.Parameters.AddWithValue("@dDOB", DBNull.Value)
         Else
            objCmd.Parameters.AddWithValue("@dDOB", cls.dDOB)
         End If
         objCmd.ExecuteNonQuery()
         objCmd.Parameters.Clear()
         objCmd.CommandText = "select last_insert_rowid()"
         cls.ID = objCmd.ExecuteScalar
         closeDbConn()
         Return cls.ID
      Catch ex As Exception
         closeDbConn()
         WriteLog("AddPeople", ex.Message)
         Return 0
      End Try
   End Function

Points of Interest

I cannot stress enough how much doing things this way will make your life easier. Readability, maintainability, and ease of coding will all contribute to enabling you to turn projects around in record time!

History

  • Added download file