Работа с БД на C#
Работа с БД на C#
Работа с базой данных — это фундаментальная задача в большинстве приложений: от простых утилит до масштабных корпоративных систем. В экосистеме .NET существует несколько подходов к взаимодействию с реляционными СУБД, и все они опираются на стандартные интерфейсы из пространства имён Система.Данные. Наиболее распространённые способы:
- ADO.NET — низкоуровневый доступ к данным через провайдеры.
- Entity Framework (EF Core) — высокоуровневый ORM (Object-Relational Mapper).
- Dapper — лёгкий микрослой поверх ADO.NET для удобного маппинга.
В этом примере рассматриваются все три подхода на основе Microsoft SQL Server и SQLite, чтобы показать разницу в уровне абстракции и объёме кода.
Подготовка: создание тестовой базы данных
Для демонстрации используется SQLite — встраиваемая СУБД без необходимости установки сервера. Файл базы создаётся автоматически при первом подключении.
SQL-скрипт для создания таблицы:
CREATE TABLE IF NOT EXISTS Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL UNIQUE,
Age INTEGER
);
1. Работа через ADO.NET (низкоуровневый подход)
ADO.NET предоставляет прямой контроль над соединением, командами и транзакциями. Этот подход требует больше шаблонного кода, но даёт максимальную гибкость.
using Система;
using Система.Данные.SQLite;
class AdoNetExample
{
private const string ConnectionString = "Данные Source=users.db;Version=3;";
static void Main()
{
// Создание таблицы
CreateUsersTable();
// Вставка записи
InsertUser("Алиса", "alice@example.com", 28);
// Чтение всех записей
ReadAllUsers();
}
static void CreateUsersTable()
{
using var connection = new SQLiteConnection(ConnectionString);
connection.Open();
string sql = @"
CREATE TABLE IF NOT EXISTS Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL UNIQUE,
Age INTEGER
);";
using var command = new SQLiteCommand(sql, connection);
command.ExecuteNonQuery();
}
static void InsertUser(string name, string email, int age)
{
using var connection = new SQLiteConnection(ConnectionString);
connection.Open();
string sql = "INSERT INTO Users (Name, Email, Age) VALUES (@name, @email, @age);";
using var command = new SQLiteCommand(sql, connection);
command.Parameters.AddWithValue("@name", name);
command.Parameters.AddWithValue("@email", email);
command.Parameters.AddWithValue("@age", age);
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine($"Добавлено строк: {rowsAffected}");
}
static void ReadAllUsers()
{
using var connection = new SQLiteConnection(ConnectionString);
connection.Open();
string sql = "SELECT Id, Name, Email, Age FROM Users;";
using var command = new SQLiteCommand(sql, connection);
using var reader = command.ExecuteReader();
while (reader.Read())
{
int id = reader.GetInt32("Id");
string name = reader.GetString("Name");
string email = reader.GetString("Email");
int age = reader.GetInt32("Age");
Console.WriteLine($"ID: {id}, Имя: {name}, Email: {email}, Возраст: {age}");
}
}
}
Особенности ADO.NET:
- Явное управление соединением (
Open,Close). - Использование параметризованных запросов для защиты от SQL-инъекций.
- Ручная обработка
DataReaderдля чтения результатов. - Отсутствие автоматического преобразования строк в объекты.
2. Работа через Entity Framework Core (ORM)
Entity Framework Core — официальный ORM от Microsoft. Он позволяет работать с базой данных через объекты C#, а не через SQL-запросы.
Шаг 1: Установка зависимостей
Добавьте пакеты через NuGet:
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
Шаг 2: Определение модели и контекста
using Microsoft.EntityFrameworkCore;
public class User
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public int Age { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Данные Source=users_ef.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity =>
{
entity.HasIndex(u => u.Email).IsUnique();
});
}
}
Шаг 3: Использование
using var context = new AppDbContext();
// Создание базы и таблиц (если не существует)
context.Database.EnsureCreated();
// Добавление пользователя
var user = new User
{
Name = "Боб",
Email = "bob@example.com",
Age = 34
};
context.Users.Add(user);
context.SaveChanges();
// Чтение всех пользователей
var allUsers = context.Users.ToList();
foreach (var u in allUsers)
{
Console.WriteLine($"ID: {u.Id}, Имя: {u.Name}, Email: {u.Email}, Возраст: {u.Age}");
}
Преимущества EF Core:
- Автоматическое создание схемы БД из моделей (Code First).
- LINQ-запросы вместо SQL.
- Отслеживание изменений объектов.
- Миграции для управления изменениями схемы.
Недостатки:
- Больший оверхед по сравнению с ADO.NET.
- Сложность отладки «сгенерированного» SQL.
3. Работа через Dapper (микро-ORM)
Dapper — лёгкая библиотека от команды Stack Overflow. Она расширяет IDbConnection, добавляя методы для автоматического маппинга результатов SQL-запросов в объекты.
Установка
dotnet add package Dapper
dotnet add package Система.Данные.SQLite
Пример использования
using Система;
using Система.Данные.SQLite;
using Dapper;
class DapperExample
{
private const string ConnectionString = "Данные Source=users_dapper.db;Version=3;";
static void Main()
{
using var connection = new SQLiteConnection(ConnectionString);
connection.Open();
// Создание таблицы
connection.Execute(@"
CREATE TABLE IF NOT EXISTS Users (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL,
Email TEXT NOT NULL UNIQUE,
Age INTEGER
);");
// Вставка
var userId = connection.Execute(
"INSERT INTO Users (Name, Email, Age) VALUES (@Name, @Email, @Age);",
new { Name = "Карина", Email = "karina@example.com", Age = 25 });
// Чтение
var users = connection.Query<User>("SELECT * FROM Users;");
foreach (var u in users)
{
Console.WriteLine($"ID: {u.Id}, Имя: {u.Name}, Email: {u.Email}, Возраст: {u.Age}");
}
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public int Age { get; set; }
}
Особенности Dapper:
- Минимальный оверхед — почти как ADO.NET по скорости.
- Автоматический маппинг полей в свойства объекта.
- Поддержка множественных результатов, списков, асинхронных операций.
- Требует написания SQL вручную, но без ручной обработки
DataReader.
Сравнение подходов
| Критерий | ADO.NET | Entity Framework Core | Dapper |
|---|---|---|---|
| Уровень абстракции | Низкий | Высокий | Средний |
| Производительность | Максимальная | Ниже из-за оверхеда | Почти как ADO.NET |
| Объём кода | Большой | Минимальный | Умеренный |
| Гибкость SQL | Полная | Ограниченная (LINQ) | Полная |
| Защита от инъекций | Через параметры | Автоматическая | Через параметры |
| Миграции | Нет | Встроены | Нет |
Рекомендации по выбору
- Используйте ADO.NET, если требуется максимальный контроль, работа с legacy-системами или высокая производительность критична.
- Выбирайте EF Core, если проект новый, команда предпочитает объектную модель, и важна скорость разработки.
- Отдавайте предпочтение Dapper, если нужно сочетать производительность ADO.NET с удобством маппинга, особенно в микросервисах или API с большим числом запросов.
Безопасность и лучшие практики
- Всегда используйте параметризованные запросы — никогда не конкатенируйте строки для формирования SQL.
- Не храните строки подключения в коде — используйте
appsettings.jsonили переменные окружения. - Оборачивайте соединения в
using, чтобы гарантировать их закрытие. - Для продакшена применяйте пулы соединений, таймауты и логирование ошибок.
- При работе с паролями или персональными данными — шифруйте их перед сохранением.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Проблема — Пользователи должны иметь возможность регистрироваться, входить в систему и получать доступ к персонализированному контенту или функционалу. Простой консольный чат на C — это учебное приложение, демонстрирующее базовые принципы сетевого взаимодействия между клиентом и сервером с использованием сокетов. Перед началом работы обязательно изучите главу Turtle . Scratch — визуальная образовательная среда программирования, разработанная MIT Media Lab. Особенности реализации — set -euo pipefail — обязательная практика для production-скриптов; - shift $((OPTIND - 1)) корректно обрабатывает как script.sh -c ., так и script.sh . -c; - -C и… echo off rem — Отключает вывод каждой команды (как set -x в bash) rem — в начале первой строки подавляет вывод её самой Примечание — использует XML-документацию, встроенную в модули. В PowerShell 7+ справка по умолчанию загружается из интернета, если локальные файлы отсутствуют. Примечание — для большинства случаев достаточно , но оно не поддерживает функции и некоторые нестандартные объекты (например, до ES2024 — поддержка есть, но не во всех средах выполнения, например,… ✅ Такой подход даёт полную типобезопасность без и без / . Подходит для лёгких сценариев или когда внешние зависимости нежелательны. ✅ Работает, если связь или гарантируется единственность. ⚠️ Для продакшена рекомендуются Jackson ( ) или Gson (более производительные и типобезопасные). удобен для прототипирования. Генератор случайных паролей — это утилита, создающая строки с заданными криптографическими свойствами — длина, наличие заглавных и строчных букв, цифр, специальных символов.Готовые решения
Простой консольный чат на CSharp
Примеры фигур Turtle на Python
Примеры скриптов Scratch
Примеры скриптов в Linux
Примеры команд в cmd
Примеры команд в PowerShell
Примеры решений в JavaScript
Примеры решений в TypeScript
Примеры запросов в SQL
Примеры решений в Java
Генератор случайных паролей на CSharp