Tutorials ADO.NET Core Tutorial

ADO.NET Architecture — Complete Guide

ADO.NET Architecture — Complete Guide: free step-by-step lesson with examples, common mistakes, and interview tips — part of ADO.NET Core Tutorial on Toolliyo Academy.

On this page
ADO.NET Architecture — Complete Guide — ShopNest.DataAccess
Article 2 of 100 · Module 1: ADO.NET Fundamentals · Payments
Target keyword: ado.net architecture ado.net core · Read time: ~22 min · .NET: 8 · ADO.NET Core · Project: ShopNest.DataAccess — Payments

Introduction

ADO.NET Architecture — Complete Guide is essential for .NET developers building ShopNest.DataAccess — Enterprise High-Performance Data Platform — Toolliyo's 100-article ADO.NET Core master path covering SqlConnection, stored procedures, transactions, connection pooling, ASP.NET Core integration, Azure SQL, and ten enterprise portfolio projects. Every article includes minimum two enterprise real-world examples (ICICI banking, TCS ERP reporting, insurance batch, legacy modernization).

In Indian delivery projects (TCS, Infosys, Wipro), interviewers expect ado.net architecture with real banking transfers, ERP GL reports, or legacy stored procedure modernization — not toy animal demos. This article delivers production depth on Payments.

After this article you will

  • Explain ADO.NET Architecture in plain English and in SQL Server / ADO.NET terms
  • Implement ado.net architecture in ShopNest.DataAccess — Enterprise High-Performance Data Platform (Payments)
  • Compare SQL-concat / sync anti-patterns vs production-ready parameterized async ADO.NET
  • Answer fresher, mid-level, and senior ADO.NET and SQL Server interview questions confidently
  • Connect this lesson to Article 3 and the 100-article ADO.NET Core roadmap

Prerequisites

Concept deep-dive

Level 1 — Analogy

ADO.NET is a direct phone line to SQL Server — your C# speaks SQL through SqlConnection without an ORM translator in the middle.

Level 2 — Technical

ADO.NET Architecture establishes ShopNest.DataAccess foundations — SqlClient stack, connection strings, and when raw ADO.NET beats EF Core for Payments.

Level 3 — Data platform view

[ASP.NET Core API / MVC Controller]
       ▼
[Application Service — IOrderRepository interface]
       ▼
[ADO.NET Repository — SqlConnection + SqlCommand + SqlParameter]
       ▼
[SQL Server — Tables · Indexes · Stored Procedures · Transactions]
       ▼
[Connection Pool · Read Replica · Azure SQL · Serilog + SQL Profiler]

Common misconceptions

❌ MYTH: ADO.NET is obsolete — always use EF Core.
✅ TRUTH: ADO.NET wins for stored procedures, bulk load, streaming reports, and legacy SQL — EF Core for rapid CRUD.

❌ MYTH: String concatenation is fine if you escape quotes.
✅ TRUTH: Always SqlParameter — SQL injection is the #1 data breach vector in Indian banking apps.

❌ MYTH: Sync database calls are fine in ASP.NET Core.
✅ TRUTH: Use async ADO.NET end-to-end — sync calls block thread pool under load.

Project structure

ShopNest.DataAccess/
├── src/
│   ├── ShopNest.DataAccess.Api/       ← ASP.NET Core Web API
│   ├── ShopNest.DataAccess.Core/      ← Repository interfaces + DTOs
│   ├── ShopNest.DataAccess.AdoNet/    ← SqlConnection, SPs, transactions
│   ├── ShopNest.DataAccess.Reports/   ← Streaming readers, GL reports
│   └── ShopNest.DataAccess.Tests/     ← Testcontainers SQL integration
├── sql/
│   ├── migrations/
│   └── stored-procedures/             ← usp_Orders_*, usp_Payments_*
└── docker-compose.yml                 ← SQL Server 2022

Hands-on implementation — Payments

Write ADO.NET Architecture in ShopNest.DataAccess for Payments: SqlConnection/SqlCommand with parameters, async calls, and verify in SSMS with execution plan.

  1. Open ShopNest.DataAccess repository for this lesson module.
  2. Use SqlConnection with await using and connection string from IConfiguration.
  3. Add SqlParameter for every user input — never string concatenation.
  4. Use ExecuteReaderAsync for reads; transactions for multi-statement writes.
  5. Verify in SSMS — check execution plan, row counts, and connection pool metrics.

Anti-pattern (SQL concat, sync calls, DataSet for huge reports)

// ❌ BAD — SQL concat, sync call, no disposal
public List<Order> GetOrders(string status) {
    var conn = new SqlConnection(_connStr);
    conn.Open();
    var cmd = new SqlCommand("SELECT * FROM Orders WHERE Status = '" + status + "'", conn);
    var reader = cmd.ExecuteReader(); // sync, blocks thread pool
    // connection never disposed — pool exhaustion under load
    return Parse(reader);
}

Production-style ADO.NET data access

// ✅ CORRECT — ADO.NET Architecture on ShopNest (Payments)
public async Task<IReadOnlyList<OrderDto>> GetByStatusAsync(string status, CancellationToken ct) {
    await using var conn = new SqlConnection(_config.GetConnectionString("ShopNestDb"));
    await conn.OpenAsync(ct);
    await using var cmd = new SqlCommand("usp_Orders_GetByStatus", conn) {
        CommandType = CommandType.StoredProcedure
    };
    cmd.Parameters.Add("@Status", SqlDbType.NVarChar, 20).Value = status;
    var list = new List<OrderDto>();
    await using var reader = await cmd.ExecuteReaderAsync(ct);
    while (await reader.ReadAsync(ct))
        list.Add(new OrderDto(reader.GetInt32(0), reader.GetDecimal(1), reader.GetString(2)));
    return list;
}

Complete example

// ADO.NET stack: SqlConnection → SqlCommand → SqlDataReader / DataAdapter
// Microsoft.Data.SqlClient for .NET 8+

ADO.NET vs EF Core vs Dapper — when to use which

CriteriaADO.NET CoreEF CoreDapper
Performance (hot path)Fastest — zero ORM overheadSlower — change tracker, LINQ translationNear ADO.NET — thin mapper
SQL controlFull — you write every SQL linePartial — LINQ to SQL, migrationsFull SQL strings + mapping
Dev speedSlower — more boilerplateFastest — migrations, conventionsFast for reads/writes
Enterprise useBanking SPs, reporting, legacyGreenfield CRUD appsHigh-perf APIs, read models
ShopNest.DataAccessPayments ledger, GL reportsAdmin CRUD, IdentityAnalytics read APIs

Rule of thumb: EF Core for productivity; ADO.NET for performance-critical SQL, stored procedures, bulk ops, and legacy SP bridges.

SQL performance and connection management — ADO.NET Architecture

  • Connection pooling — default enabled; never disable without load testing; watch pool exhaustion (error 10053/10054)
  • Parameterized queries — always use SqlParameter; prevents SQL injection and enables plan cache reuse
  • Async — ExecuteReaderAsync/ExecuteNonQueryAsync free thread pool under load
  • CommandBehavior.SequentialAccess — stream large BLOB/text columns without loading full row into memory
  • Indexes — align with WHERE/JOIN columns; use SQL Server DMVs to find missing indexes

Real-World Example 1 — Hospital Patient Records (Apollo-Style)

MANDATORY enterprise scenario (Healthcare): ADO.NET Architecture in ShopNest.DataAccess Payments.

Business problem

Patient vitals, lab results, and billing hit different schemas. ADO.NET multi-result sets from usp_GetPatientDashboard return 3 grids in one round trip — faster than 3 EF Core queries with Include chains.

Architecture

usp_GetPatientDashboard @PatientId → Result set 1: Demographics
  → Result set 2: Latest vitals → Result set 3: Pending bills

Production ADO.NET code

await using var reader = await cmd.ExecuteReaderAsync(ct);
var demo = ReadDemographics(reader);
await reader.NextResultAsync(ct);
var vitals = ReadVitals(reader);
await reader.NextResultAsync(ct);
var bills = ReadBills(reader);

Outcome

Dashboard load 320ms vs 890ms EF Core; HIPAA audit trail via ADO.NET audit interceptor.

Real-World Example 2 — ICICI-Style NEFT/IMPS Fund Transfer

MANDATORY enterprise scenario (Indian Banking): ADO.NET Architecture in ShopNest.DataAccess Payments.

Business problem

Core banking must process 50,000+ transfers per hour during salary day. EF Core change tracking adds overhead; ADO.NET with stored procedures and explicit SqlTransaction gives predictable latency and full SQL control for auditors.

Architecture

[Mobile Banking API] → [TransferRepository (ADO.NET)]
  → SqlConnection (pooled) → usp_TransferFunds @FromAcct, @ToAcct, @Amount
  → SqlTransaction (Serializable for ledger rows)
  → AuditLog INSERT via usp_WriteAuditTrail
Connection string: ShopNestPaymentsDb; CommandTimeout: 30s; Retry on deadlock 1205.

Production ADO.NET code

// ShopNest.DataAccess/Payments/TransferRepository.cs
public async Task<TransferResult> TransferAsync(TransferRequest req, CancellationToken ct)
{
    await using var conn = new SqlConnection(_connectionString);
    await conn.OpenAsync(ct);
    await using var tx = (SqlTransaction)await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted, ct);

    try
    {
        await using var cmd = new SqlCommand("usp_TransferFunds", conn, tx)
        {
            CommandType = CommandType.StoredProcedure,
            CommandTimeout = 30
        };
        cmd.Parameters.Add("@FromAccount", SqlDbType.VarChar, 20).Value = req.FromAccount;
        cmd.Parameters.Add("@ToAccount", SqlDbType.VarChar, 20).Value = req.ToAccount;
        cmd.Parameters.Add("@Amount", SqlDbType.Decimal).Value = req.Amount;
        cmd.Parameters.Add("@IdempotencyKey", SqlDbType.UniqueIdentifier).Value = req.IdempotencyKey;

        var rows = await cmd.ExecuteNonQueryAsync(ct);
        await tx.CommitAsync(ct);
        return TransferResult.Success(req.IdempotencyKey);
    }
    catch (SqlException ex) when (ex.Number == 1205) // deadlock
    {
        await tx.RollbackAsync(ct);
        throw new TransientDatabaseException("Deadlock — retry with Polly", ex);
    }
}

Outcome

P99 transfer latency 45ms vs 180ms with EF Core tracked entities; RBI audit passed with stored procedure versioning.

ADO.NET with ASP.NET Core — ADO.NET Architecture

Register IPaymentsRepository as Scoped in DI. Never hold SqlConnection across requests. Use IConfiguration for connection strings; User Secrets locally, Azure Key Vault in production.

builder.Services.AddScoped<IOrderRepository, OrderRepository>();
builder.Services.AddHealthChecks().AddSqlServer(connectionString);

Stored procedures and SQL safety

Enterprise ShopNest modules use versioned stored procedures (usp_ prefix). Never concatenate user input — always SqlParameter. Log slow queries (>500ms) with Serilog and review execution plans in SSMS.

Common errors & fixes

  • SQL built with string concatenation from user input — Use SqlParameter with typed values for every dynamic value.
  • Not disposing SqlConnection / SqlDataReader — Use await using for connection, command, and reader — return connections to pool.
  • Loading million-row reports into DataTable — Stream with SqlDataReader and yield batches; avoid DataSet for large data.
  • Hard-coding connection strings in repository classes — IConfiguration + User Secrets locally; Azure Key Vault in production.

Best practices

  • 🟢 SqlParameter for every dynamic value — zero string concatenation
  • 🟢 await using for SqlConnection, SqlCommand, SqlDataReader — return to pool
  • 🟡 Async ADO.NET end-to-end on ASP.NET Core request paths
  • 🟡 Stream large reports with SqlDataReader; avoid DataSet for millions of rows
  • 🔴 SqlTransaction for multi-statement financial writes with explicit rollback
  • 🔴 Connection strings in Key Vault — never committed to Git

Interview questions

Fresher level

Q1: What is ADO.NET Architecture in ADO.NET Core?
A: ADO.NET Architecture on ShopNest Payments: SqlConnection lifecycle, SqlCommand with parameters, async execution, and disposal for connection pool health.

Q2: ADO.NET vs EF Core — when to use which?
A: ADO.NET for stored procedures, bulk load, streaming reports, and legacy SQL; EF Core for rapid CRUD and migrations. ShopNest uses both.

Q3: How do you prevent SQL injection in ADO.NET?
A: Always SqlParameter with typed SqlDbType — never string concatenation, even for "trusted" internal tools.

Mid / senior level

Q4: Explain connection pooling and why disposal matters.
A: SqlConnection.Close/Dispose returns the physical connection to the pool. Leaked connections exhaust Max Pool Size and cause timeouts.

Q5: How do you handle transactions in ADO.NET?
A: SqlTransaction with try/commit/catch/rollback; choose isolation level (ReadCommitted default); retry deadlocks with Polly.

Q6: How would you optimize a slow stored procedure report?
A: Check execution plan in SSMS, add covering indexes, avoid SELECT *, stream with SqlDataReader, consider read replica for analytics.

Coding round

Implement a parameterized ADO.NET repository method for ShopNest Payments — show SqlConnection, SqlCommand, SqlParameter, async disposal, and one xUnit integration test.

Summary & next steps

  • Article 2: ADO.NET Architecture — Complete Guide
  • Module: Module 1: ADO.NET Fundamentals · Level: BEGINNER
  • Applied to ShopNest.DataAccess — Payments

Previous: Introduction to ADO.NET Core — Complete Guide
Next: ADO.NET vs EF Core vs Dapper — Complete Guide

Practice: Run today's SQL in SSMS with execution plan — commit with feat(adonet): article-002.

FAQ

Q1: What is ADO.NET Architecture?

ADO.NET Architecture helps ShopNest.DataAccess implement high-performance Payments data access with Microsoft.Data.SqlClient and SQL Server.

Q2: Do I need EF Core to learn ADO.NET?

No — ADO.NET is the foundation. Many Indian banking and ERP projects still rely on stored procedures wrapped in ADO.NET.

Q3: Is ADO.NET asked in interviews?

Yes — SqlConnection, parameters, transactions, and ADO.NET vs EF appear in TCS, Infosys, and product company .NET rounds.

Q4: Which .NET version?

Examples target .NET 8 LTS with Microsoft.Data.SqlClient and async ADO.NET throughout.

Q5: How does this fit ShopNest.DataAccess?

Article 2 strengthens Payments. By Article 100 you have a portfolio-ready enterprise data layer.

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet — be the first to ask!

ADO.NET Core Tutorial
Course syllabus

ADO.NET Core Tutorial

Module 1: ADO.NET Fundamentals
Module 2: CRUD Operations
Module 3: Stored Procedures
Module 4: Transactions and Error Handling
Module 5: Performance Optimization
Module 6: ASP.NET Core Integration
Module 7: Advanced Enterprise Topics
Module 8: Testing and Debugging
Module 9: Cloud and DevOps
Module 10: Real-World Enterprise Projects
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details