VB.NET

Build a Database Record Navigator in VB.NET with ADO.NET

Desktop applications often need to display and move through database records one at a time. ADO.NET gives VB.NET developers the tools to connect to SQL Server and manage data operations. Building a basic navigation form teaches the core concepts that apply whether you're building a simple student tracker or a complex inventory system.

This walkthrough creates a complete record browser using Windows Forms. You'll set up a SQL Server table, design the interface, and wire up four navigation buttons that handle every edge case.

Setting Up the SQL Server Database

Start by opening Visual Studio and creating a new Windows Forms Application in VB.NET. Once the project loads, open Server Explorer from the View menu. Right-click on the Data Connections node and choose Add Connection.

If your SQL Server instance is local, enter localhost or a period as the server name. Choose Windows Authentication for simplicity, then select or create a new database. Call it StudentDatabase.

With the database created, expand it in Server Explorer and locate the Tables folder. Right-click and select Add New Table. Define four columns: StudentID (int, primary key), FirstName (nvarchar(50)), LastName (nvarchar(50)), and Grade (int). Save the table as Student.

Right-click the Student table and choose Show Table Data. Add five or six sample records covering different names and grade values. Save and close the table view.

Now right-click the database entry in Server Explorer and select Properties. Find the Connection String field and copy its entire value. You'll paste this into your code next.

Designing the Windows Forms Interface

Switch to the form designer. Add four TextBox controls in a vertical stack on the left side of the form, each labeled with their corresponding database field. On the right side, place four Button controls labeled First, Previous, Next, and Last. Arrange them so Previous sits above Next, with First and Last above and below that pair respectively.

The layout mirrors a classic record browser found in desktop database applications. The text boxes display the current record while buttons control movement.

Writing the Data Access Code

Double-click the form's title bar to generate the Form_Load event handler. Add the following imports at the top of your code file:

“`vb

Imports System.Data

Imports System.Data.SqlClient

“`

Inside Form_Load, declare your connection and data objects, then open the connection and fill a DataSet:

“`vb

Dim conn As SqlConnection

Dim adapter As SqlDataAdapter

Dim records As DataSet

Dim position As Integer = 0

Dim total As Integer

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Conn = New SqlConnection("your connection string here")

Conn.Open()

Adapter = New SqlDataAdapter("SELECT * FROM Student", conn)

Records = New DataSet()

Adapter.Fill(records, "Student")

Total = records.Tables("Student").Rows.Count

ShowRecord(0)

End Sub

“`

The ShowRecord subroutine takes an index and displays the corresponding row in your text boxes:

“`vb

Private Sub ShowRecord(idx As Integer)

Dim row As DataRow

Row = records.Tables("Student").Rows(idx)

TxtID.Text = row(0).ToString

TxtFirst.Text = row(1).ToString

TxtLast.Text = row(2).ToString

TxtGrade.Text = row(3).ToString

Position = idx

End Sub

“`

Wiring Up the Navigation Buttons

Double-click the First button and add this code:

“`vb

Private Sub btnFirst_Click(sender As Object, e As EventArgs) Handles btnFirst.Click

ShowRecord(0)

End Sub

“`

The Last button jumps to the final position:

“`vb

Private Sub btnLast_Click(sender As Object, e As EventArgs) Handles btnLast.Click

ShowRecord(total – 1)

End Sub

“`

For the Next button, we need to check if we're already at the end before advancing:

“`vb

Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click

If position < total – 1 Then

ShowRecord(position + 1)

Else

BtnLast.PerformClick()

End If

End Sub

“`

The Previous button follows the same pattern in reverse:

“`vb

Private Sub btnPrev_Click(sender As Object, e As EventArgs) Handles btnPrev.Click

If position > 0 Then

ShowRecord(position – 1)

Else

BtnFirst.PerformClick()

End If

End Sub

“`

Notice that reaching a boundary triggers the boundary button instead of doing nothing. This gives users clear feedback that they've reached the start or end of the dataset.

Why This Approach Works

The DataSet acts as an in-memory copy of your query results. Because records load once during form initialization, navigation stays instant even on slower connections. The index variable tracks your current position and gets validated before every move.

This offline-first model differs from approaches that query the database for each movement. It trades some memory usage for better responsiveness, which usually wins in desktop scenarios.

A Practical Extension

Say you want to add Edit and Delete buttons to this form. The Edit button would switch text boxes to editable mode and enable a Save button. The Delete button would remove the current row from the DataTable and call SqlCommandBuilder with your adapter to generate the DELETE SQL. Then ShowRecord would refresh the current position or move to the previous valid record if you deleted the last entry.

These additions build directly on the navigation foundation. Once you understand how the DataSet stores records and how position controls what displays, adding, modifying, and removing records follow the same logical patterns.

Bottom Line

ADO.NET's disconnected model makes building record browsers straightforward. Load data once into a DataSet, track position with a simple integer, and update the display after every move. The boundary checks prevent crashes while giving users predictable behavior at the edges of their data.

Key takeaways

  • DataSet objects cache query results locally for smooth navigation
  • SqlDataAdapter bridges SQL queries and in-memory data tables
  • Boundary validation stops index errors when users reach dataset limits
  • The navigation pattern extends cleanly to support editing and deletion

Frequently asked questions

Can I use this approach with Access or MySQL instead of SQL Server?

Yes, swap SqlConnection for OleDbConnection or MySqlConnection and adjust the connection string syntax accordingly.

What happens if the table is empty when the form loads?

The Fill method returns zero rows, so total equals zero. The navigation buttons would all trigger their boundary counterparts immediately.

Is this pattern still recommended for new projects?

Entity Framework offers more modern alternatives, but ADO.NET remains solid for performance-critical applications and learning database fundamentals.

How do I add a new record instead of just viewing existing ones?

Create a new DataRow using table.NewRow(), populate its fields, add it to the table, and call adapter.Update() to sync changes back to the database.

Can I filter which records appear without changing the query?

Use the DataTable.Select method to create filtered views, or apply a DataView with a RowFilter expression before binding to your interface.

Related