Работа с базами данных в C#: PostgreSQL и MongoDB на практике
Работа с базами данных — одна из ключевых задач любого backend-разработчика. В экосистеме C# (.NET) разработчику доступны сотни драйверов и ORM, но наиболее востребованными остаются реляционные СУБД (PostgreSQL) и документо-ориентированные NoSQL-решения (MongoDB). В этой статье мы на практических примерах разберём, как подключаться к обеим базам, выполнять CRUD-операции и выбирать подходящий инструмент под конкретную задачу.
1. PostgreSQL в C#: подключение и CRUD через Npgsql
Для работы с PostgreSQL в .NET используется библиотека Npgsql — высокопроизводительный ADO.NET-провайдер. Установим её через NuGet:
dotnet add package Npgsql
1.1. Подключение к базе данных
Строка подключения для локального сервера PostgreSQL выглядит так:
string connectionString = "Host=localhost;Port=5432;Database=testdb;Username=postgres;Password=your_password";
Создадим класс-помощник для работы с БД:
using Npgsql;
public class PostgresService
{
private readonly string _connectionString;
public PostgresService(string connectionString)
{
_connectionString = connectionString;
}
public async Task InsertUserAsync(string name, int age)
{
await using var conn = new NpgsqlConnection(_connectionString);
await conn.OpenAsync();
var cmd = new NpgsqlCommand(
"INSERT INTO users (name, age) VALUES (@name, @age)", conn);
cmd.Parameters.AddWithValue("name", name);
cmd.Parameters.AddWithValue("age", age);
await cmd.ExecuteNonQueryAsync();
}
public async Task<List<User>> GetAllUsersAsync()
{
var users = new List<User>();
await using var conn = new NpgsqlConnection(_connectionString);
await conn.OpenAsync();
var cmd = new NpgsqlCommand("SELECT id, name, age FROM users", conn);
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
users.Add(new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Age = reader.GetInt32(2)
});
}
return users;
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
1.2. Использование Entity Framework Core с PostgreSQL
Для более удобной работы с реляционными данными используйте ORM Entity Framework Core с провайдером Npgsql.EntityFrameworkCore.PostgreSQL:
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
Пример модели и контекста:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("Host=localhost;Database=testdb;Username=postgres;Password=your_password");
}
}
Теперь CRUD-операции становятся тривиальными:
using (var db = new AppDbContext())
{
// Create
db.Users.Add(new User { Name = "Alice", Age = 30 });
db.SaveChanges();
// Read
var users = db.Users.ToList();
// Update
var user = db.Users.First();
user.Age = 31;
db.SaveChanges();
// Delete
db.Users.Remove(user);
db.SaveChanges();
}
2. MongoDB в C#: работа с документами через официальный драйвер
MongoDB — документная NoSQL база, где данные хранятся в формате BSON. Для C# существует мощный официальный драйвер MongoDB.Driver.
2.1. Установка и подключение
dotnet add package MongoDB.Driver
Подключение к локальному серверу:
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("testdb");
var collection = database.GetCollection<BsonDocument>("users");
2.2. CRUD-операции с типизированными классами
Рекомендуется работать не с BsonDocument, а с POCO-классами:
public class User
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public List<string> Tags { get; set; }
}
Пример сервиса:
using MongoDB.Driver;
public class MongoService
{
private readonly IMongoCollection<User> _usersCollection;
public MongoService()
{
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("testdb");
_usersCollection = database.GetCollection<User>("users");
}
public async Task InsertUserAsync(User user)
{
await _usersCollection.InsertOneAsync(user);
}
public async Task<List<User>> GetAllUsersAsync()
{
return await _usersCollection.Find(_ => true).ToListAsync();
}
public async Task<User> GetUserByNameAsync(string name)
{
return await _usersCollection.Find(u => u.Name == name).FirstOrDefaultAsync();
}
public async Task UpdateUserAgeAsync(string name, int newAge)
{
var filter = Builders<User>.Filter.Eq(u => u.Name, name);
var update = Builders<User>.Update.Set(u => u.Age, newAge);
await _usersCollection.UpdateOneAsync(filter, update);
}
public async Task DeleteUserAsync(string name)
{
await _usersCollection.DeleteOneAsync(u => u.Name == name);
}
}
3. PostgreSQL vs MongoDB: когда что выбирать?
Выбор между реляционной и документной базой — не техническая, а архитектурная задача. Рассмотрим критерии:
- Структура данных: если данные строго типизированы, нормализованы и требуют сложных JOIN — выбирайте PostgreSQL. Если данные слабоструктурированы или часто меняют схему — MongoDB.
- Транзакции и ACID: PostgreSQL полностью поддерживает ACID-транзакции. MongoDB с версии 4.0 также поддерживает транзакции, но с ограничениями.
- Гибкость схемы: MongoDB позволяет хранить в одной коллекции документы с разными полями — это удобно для прототипирования.
- Производительность: MongoDB быстрее на опера