Working with Data in .NET
This section provides a comprehensive guide to accessing and manipulating data within the .NET ecosystem. Whether you're working with relational databases, NoSQL stores, or cloud-based services, .NET offers robust and efficient tools.
ADO.NET: The Foundation of Data Access
ADO.NET is a set of classes that expose data access services to .NET programmers. It provides a consistent interface for accessing data sources such as SQL Server and XML, as well as data sources exposed by an application.
Connections
Establishing a connection to your data source is the first step. This involves using connection strings to specify server details, authentication credentials, and database names.
using System.Data.SqlClient;
// ...
string connectionString = "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// ... perform operations
}
Commands
Commands are used to execute SQL statements (like SELECT, INSERT, UPDATE, DELETE) or stored procedures against your database.
using System.Data.SqlClient;
// ...
using (SqlCommand command = new SqlCommand("SELECT COUNT(*) FROM MyTable", connection))
{
int count = (int)command.ExecuteScalar();
Console.WriteLine($"Number of records: {count}");
}
DataReaders
SqlDataReader
(or its equivalent for other providers) is an efficient way to retrieve data from a database in a forward-only, read-only manner. It's ideal for large result sets where you don't need to load all data into memory.
using System.Data.SqlClient;
// ...
using (SqlCommand command = new SqlCommand("SELECT Id, Name FROM MyTable", connection))
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
int id = reader.GetInt32(0);
string name = reader.GetString(1);
Console.WriteLine($"ID: {id}, Name: {name}");
}
}
DataSets
DataSet
is an in-memory representation of data. It can hold multiple tables, relationships, and constraints, allowing for disconnected data manipulation.
DataSet
can consume significant memory. Consider DataReader
for performance-critical scenarios with large datasets.
using System.Data.SqlClient;
using System.Data;
// ...
DataTable dataTable = new DataTable();
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM MyTable", connection))
{
adapter.Fill(dataTable);
}
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine($"Row: {row["Name"]}");
}
Entity Framework Core (EF Core): The Modern ORM
Entity Framework Core is a powerful, open-source, cross-platform object-relational mapper (ORM) for .NET. It enables developers to work with databases using .NET objects instead of raw SQL statements.
DbContext
The DbContext
class is the primary class that interfaces with your database. It represents a session with the database and allows you to query and save data.
using Microsoft.EntityFrameworkCore;
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=BloggingEFCore;Trusted_Connection=True;");
}
}
Migrations
Migrations are EF Core's way of evolving your database schema to match your C# model. You can generate and apply migrations to create or update your database.
// In Package Manager Console:
// Add-Migration InitialCreate
// Update-Database
Querying Data
EF Core allows you to query data using LINQ (Language Integrated Query).
using (var db = new BloggingContext())
{
var blogs = db.Blogs.Where(b => b.Rating > 3).OrderBy(b => b.Url).ToList();
foreach (var blog in blogs)
{
Console.WriteLine($"Blog: {blog.Url}");
}
}
Saving Data
Adding, updating, and deleting entities is straightforward with DbContext
.
using (var db = new BloggingContext())
{
// Add
db.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
db.SaveChanges();
// Update
var blogToUpdate = db.Blogs.FirstOrDefault(b => b.Url == "http://blogs.msdn.com/adonet");
if (blogToUpdate != null)
{
blogToUpdate.Url = "http://blogs.msdn.com/entityframework";
db.SaveChanges();
}
// Delete
var blogToDelete = db.Blogs.FirstOrDefault(b => b.Url == "http://blogs.msdn.com/entityframework");
if (blogToDelete != null)
{
db.Remove(blogToDelete);
db.SaveChanges();
}
}
Other Data Access Technologies
Beyond ADO.NET and EF Core, .NET supports various other data access patterns and libraries, including:
- Dapper: A popular micro-ORM that offers excellent performance.
- LINQ to SQL: An older ORM that is part of .NET Framework but less recommended for new projects compared to EF Core.
- Data Access Components for specific cloud providers (e.g., Azure Cosmos DB SDK, AWS SDK for .NET).
Best Practices for Data Access
To ensure your applications are performant, secure, and maintainable, consider these best practices:
- Use Parameterized Queries: Always use parameterized queries to prevent SQL injection vulnerabilities.
- Dispose of Resources: Ensure that database connections, commands, and readers are properly disposed of (using
using
statements is highly recommended). - Optimize Queries: Write efficient SQL queries and leverage indexing in your database.
- Choose the Right Technology: Select the data access technology that best suits your project's needs (e.g., ADO.NET for raw performance, EF Core for rapid development and ORM features).
- Handle Concurrency: Implement strategies for managing concurrent data modifications.
- Error Handling: Implement robust error handling for database operations.