Skip to main content
C# Fundamentals for Beginners to Advanced
CHAPTER 25 Beginner

Database Programming with ADO.NET

Updated: May 17, 2026
5 min read

# CHAPTER 25

Database Programming with ADO.NET

1. Introduction

While file handling (Chapter 22) is great for simple notes, enterprise applications require robust databases to manage thousands of users, transactions, and relational data. ADO.NET (ActiveX Data Objects for .NET) is the core Microsoft framework that allows your C# code to talk directly to databases like Microsoft SQL Server.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the Connection String.
  • Use SqlConnection to connect to a database.
  • Execute SQL queries using SqlCommand.
  • Read database rows using SqlDataReader.
  • Prevent SQL Injection using Parameters.

3. Required NuGet Package

In modern .NET, you must install the SQL Client package before coding. Open your terminal and run: dotnet add package Microsoft.Data.SqlClient

4. The Connection String

A connection string is a secure URL that tells C# exactly where the database is, what it's named, and how to log in.
csharp
12
// Example string for a local SQL Server Express database
string connString = "Server=localhost\\SQLEXPRESS;Database=SchoolDB;Integrated Security=True;TrustServerCertificate=True;";

5. Connecting and Reading Data

We use three main classes: SqlConnection (opens the door), SqlCommand (sends the SQL query), and SqlDataReader (reads the response).
csharp
1234567891011121314151617181920212223242526272829303132333435
using System;
using Microsoft.Data.SqlClient; // Required!

class Program
{
    static void Main()
    {
        string connString = "Server=localhost;Database=SchoolDB;Integrated Security=True;TrustServerCertificate=True;";

        // 1. Create Connection inside a using block (auto-closes)
        using (SqlConnection conn = new SqlConnection(connString))
        {
            // 2. Open the connection
            conn.Open();
            Console.WriteLine("Database Connected!");

            // 3. Write the SQL Query
            string query = "SELECT Id, Name FROM Students";

            // 4. Execute the Command
            using (SqlCommand cmd = new SqlCommand(query, conn))
            {
                // 5. Read the Results
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        // Access columns by Index or Name
                        Console.WriteLine($"ID: {reader[0]} | Name: {reader["Name"]}");
                    }
                }
            }
        } // Connection automatically closes here!
    }
}

6. Inserting Data (Executing Non-Queries)

If your SQL statement does not return rows (e.g., INSERT, UPDATE, DELETE), you use ExecuteNonQuery() instead of ExecuteReader().
csharp
123456789101112
using (SqlConnection conn = new SqlConnection(connString))
{
    conn.Open();
    string insertQuery = "INSERT INTO Students (Name, Age) VALUES ('John', 20)";
    
    using (SqlCommand cmd = new SqlCommand(insertQuery, conn))
    {
        // ExecuteNonQuery returns the number of rows affected
        int rowsAffected = cmd.ExecuteNonQuery();
        Console.WriteLine($"{rowsAffected} row(s) inserted.");
    }
}

7. Preventing SQL Injection (CRITICAL)

Never concatenate user input directly into a SQL string: "INSERT INTO Students VALUES ('" + userInput + "')" If the user types 'DROP TABLE Students;--, they will delete your entire database!

The Solution: Parameterized Queries.

csharp
12345678910
string insertQuery = "INSERT INTO Students (Name, Age) VALUES (@studentName, @studentAge)";

using (SqlCommand cmd = new SqlCommand(insertQuery, conn))
{
    // Securely bind the user input to the @ parameters
    cmd.Parameters.AddWithValue("@studentName", "Alice");
    cmd.Parameters.AddWithValue("@studentAge", 22);
    
    cmd.ExecuteNonQuery();
}

8. Common Mistakes

  • Leaving Connections Open: If you forget to call conn.Close() (or forget the using block), you will run out of connections in the SQL Server Connection Pool, and your entire application will crash.
  • SQL Injection Vulnerabilities: Failing to use cmd.Parameters.AddWithValue is the #1 cause of database hacks.

9. Best Practices

  • Never hardcode the connection string inside Program.cs. In real apps, store it securely in an appsettings.json file or Environment Variables.
  • Always wrap ADO.NET objects (SqlConnection, SqlCommand, SqlDataReader) in using blocks.

10. Exercises

  1. 1. Write a C# program that connects to a local SQL database and runs an UPDATE query to change a student's age based on their ID. Use parameterized queries.

11. MCQs with Answers

Q1. What does ADO.NET do? a) Compiles C# code b) Provides classes for connecting C# applications to databases c) Handles UI rendering Answer: b) Provides classes for connecting C# applications to databases
Question 2

Which package is required to connect to SQL Server in modern .NET?

Question 3

What information is held in a Connection String?

# code Answer: a) Server location, database name, and credentials
Question 4

Which class establishes the actual link to the database?

Question 5

Which method executes a SELECT statement and returns rows?

Question 6

Which method executes an INSERT, UPDATE, or DELETE statement?

Question 7

What does ExecuteNonQuery() return?

Question 8

What is SQL Injection?

Question 9

How do you prevent SQL Injection in ADO.NET?

Question 10

Why must SqlConnection be placed inside a using block?

12. Interview Questions

  • Q: Differentiate between ExecuteReader(), ExecuteNonQuery(), and ExecuteScalar().
  • Q: Explain what Connection Pooling is and why it matters in ADO.NET.
  • Q: Demonstrate how to write a SQL query in C# that is 100% immune to SQL injection.

13. Summary

ADO.NET provides the raw, low-level classes (SqlConnection, SqlCommand, SqlDataReader) needed to execute SQL commands from C#. While extremely fast and powerful, it requires careful memory management (using blocks) and security vigilance (Parameterized Queries) to prevent SQL Injection.

14. Next Chapter Recommendation

Writing raw SQL strings inside C# code is prone to typos and is difficult to maintain. In Chapter 27: Entity Framework Core Basics, we will learn how to replace ADO.NET with a modern ORM, allowing us to manage databases using pure C# objects! (But first, a brief detour to the web in Chapter 26).

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·