Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

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

0.00/5 (No votes)
16 Aug 2015 1  
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

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