.NET Database Access

This section provides comprehensive guidance on how to interact with databases from your .NET applications. We'll cover various approaches, from low-level data manipulation to high-level Object-Relational Mappers (ORMs).

Core Technologies

The .NET ecosystem offers several powerful technologies for database connectivity:

ADO.NET

ADO.NET is a set of classes that expose data access services to the .NET Framework. It provides a consistent interface to access various data sources, including relational databases, XML, and other data sources.

Entity Framework Core

Entity Framework (EF) Core is a modern, open-source, cross-platform version of the popular Entity Framework data access technology. It allows developers to work with databases using .NET objects, abstracting away much of the direct SQL interaction.

Other Data Access Libraries

Explore other libraries and best practices:

Connecting to a Database (ADO.NET)

Establishing a connection is the first step. You'll typically use a connection string that specifies the server, database name, and authentication details.


using System;
using System.Data.SqlClient; // For SQL Server

public class DatabaseConnector
{
    public static void Main(string[] args)
    {
        string connectionString = "Server=myServerAddress;Database=myDatabase;User Id=myUsername;Password=myPassword;";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            try
            {
                connection.Open();
                Console.WriteLine("Connection successful!");
            }
            catch (SqlException ex)
            {
                Console.WriteLine($"Error connecting to database: {ex.Message}");
            }
        }
    }
}
        

Note: Always use parameterized queries to prevent SQL injection vulnerabilities.

Executing Commands (ADO.NET)

Once connected, you can execute SQL commands like INSERT, UPDATE, DELETE, and SELECT.


using System.Data.SqlClient;

// ... inside a method after opening connection ...

string query = "INSERT INTO Products (Name, Price) VALUES (@Name, @Price)";
using (SqlCommand command = new SqlCommand(query, connection))
{
    command.Parameters.AddWithValue("@Name", "Awesome Gadget");
    command.Parameters.AddWithValue("@Price", 199.99);

    int rowsAffected = command.ExecuteNonQuery();
    Console.WriteLine($"{rowsAffected} row(s) inserted.");
}
        

Reading Data (ADO.NET)

For SELECT statements, you'll typically use a SqlDataReader to iterate through results.


using System.Data.SqlClient;

// ... inside a method after opening connection ...

string query = "SELECT ProductID, Name, Price FROM Products WHERE Price > @MinPrice";
using (SqlCommand command = new SqlCommand(query, connection))
{
    command.Parameters.AddWithValue("@MinPrice", 100.00);

    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            Console.WriteLine($"ID: {reader["ProductID"]}, Name: {reader["Name"]}, Price: {reader["Price"]}");
        }
    }
}
        

DataAdapters and Datasets (ADO.NET)

SqlDataAdapter and DataSet are useful for retrieving large amounts of data at once and working with it offline.


using System.Data.SqlClient;
using System.Data;

// ... inside a method after opening connection ...

string query = "SELECT * FROM Customers";
using (SqlDataAdapter adapter = new SqlDataAdapter(query, connection))
{
    DataSet dataSet = new DataSet();
    adapter.Fill(dataSet, "Customers");

    // Access data from the DataTable
    DataTable customersTable = dataSet.Tables["Customers"];
    foreach (DataRow row in customersTable.Rows)
    {
        Console.WriteLine($"Name: {row["CompanyName"]}");
    }
}
        

Getting Started with Entity Framework Core

EF Core simplifies data access by mapping your classes to database tables.

Tip: Install the necessary EF Core NuGet packages (e.g., Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.Tools).

Defining Your Model


public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
        

Configuring the DbContext


using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Replace with your actual connection string
        optionsBuilder.UseSqlServer("Server=myServerAddress;Database=myDatabase;User Id=myUsername;Password=myPassword;");
    }
}
        

Performing Operations


using (var context = new AppDbContext())
{
    // Add a new product
    context.Products.Add(new Product { Name = "Super Widget", Price = 49.99M });
    context.SaveChanges();

    // Query products
    var expensiveProducts = context.Products.Where(p => p.Price > 50.00M).ToList();
    foreach (var product in expensiveProducts)
    {
        Console.WriteLine(product.Name);
    }
}
        

Migrations (EF Core)

EF Core Migrations allow you to evolve your database schema over time in sync with your application's data model.

To add a migration:


dotnet ef migrations add InitialCreate
        

To apply migrations to the database:


dotnet ef database update
        

Important: Always back up your database before applying migrations in a production environment.

LINQ Queries with EF Core

Language Integrated Query (LINQ) makes querying data concise and powerful.


// Find products containing "Widget" in their name
var widgets = context.Products.Where(p => p.Name.Contains("Widget")).ToList();

// Order products by price descending
var sortedProducts = context.Products.OrderByDescending(p => p.Price).ToList();

// Select specific properties
var productNamesAndPrices = context.Products.Select(p => new { p.Name, p.Price }).ToList();
        

For more advanced topics like transactions, stored procedures, and different database providers, please refer to the official ADO.NET documentation and the Entity Framework Core documentation.