Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Connections, Commands, and Parameterized Queries

โญโญ intermediateโณ 18 min read๐Ÿ“ Lesson 132 of 265

The ADO.NET object model, why parameters are non-negotiable, and transactions as all-or-nothing units.

The relational object model

Every data access stack shares this shape (ADO.NET, EF Core underneath, and every other runtime):

  • Connection โ€” the session to the database. Open late, close early; pool them (like HttpClient).
  • Command โ€” SQL text plus parameters. ExecuteReader for queries, ExecuteNonQuery for mutations.
  • Reader โ€” a forward-only cursor over result rows; each row maps to your object (reading columns by name, converting types).
var cmd = db.CreateCommand("SELECT * FROM users WHERE name = @name");
cmd.AddParameter("@name", userName);
var rows = db.ExecuteReader(cmd);
foreach (var row in rows)
    Console.WriteLine(row["name"]);

SQL injection: the one rule that saves you

Never build SQL by concatenating values:

// FATAL: a name like '; DROP TABLE users; -- becomes part of the program
var sql = "SELECT * FROM users WHERE name = '" + input + "'";

Parameters keep DATA as data โ€” the engine sends the query text and the values separately, so a value can never change the query's meaning. This is structural, not optional; string-built queries with user input are a vulnerability even when you "know" the input is clean.

Transactions: all or nothing

Multiple related writes must succeed or fail together โ€” a transfer that debits but never credits is a corrupted ledger. Begin marks the unit, Commit makes it permanent, and any failure (or abort) rolls back everything since Begin.

Check your understanding

  • Why can't an attacker inject through a parameter? (Values travel separately from the SQL text โ€” they're never parsed as code.)
  • When does a transaction help? (Multiple related writes that must be atomic.)