Bancos de Dados para .NET Senior
📋 Visão Geral
A escolha do banco de dados é uma decisão arquitetural crítica que impacta diretamente a performance, escalabilidade e manutenibilidade da aplicação. Este guia aborda os principais tipos de bancos de dados e quando usar cada um.
🗄️ Bancos de Dados Relacionais (RDBMS)
SQL Server
O que é: Sistema de gerenciamento de banco de dados relacional da Microsoft.
Características:
- ACID compliance
- Transações complexas
- Stored procedures
- Triggers
- Views
- Índices clustered/non-clustered
- Partitioning
- Always On Availability Groups
Benefícios:
- Integração nativa com .NET
- Ferramentas robustas (SSMS, Profiler)
- Suporte a JSON nativo
- Machine Learning Services
- PolyBase para big data
Performance:
- Leitura: Excelente com índices adequados
- Escrita: Boa para transações OLTP
- Escalabilidade: Vertical (mais recursos)
- Concorrência: Row-level locking
Casos de Uso:
- Aplicações empresariais .NET
- Sistemas transacionais (OLTP)
- Data warehousing
- Business Intelligence
- Aplicações que precisam de transações complexas
// Exemplo: Conexão com SQL Server
public class SqlServerRepository
{
private readonly string _connectionString;
public SqlServerRepository(string connectionString)
{
_connectionString = connectionString;
}
public async Task<List<Order>> GetOrdersAsync()
{
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
var sql = @"
SELECT o.OrderId, o.CustomerId, o.Total, o.Status, o.CreatedAt,
c.Name as CustomerName
FROM Orders o
INNER JOIN Customers c ON o.CustomerId = c.CustomerId
WHERE o.Status = @Status
ORDER BY o.CreatedAt DESC";
var orders = await connection.QueryAsync<Order>(sql, new { Status = "Active" });
return orders.ToList();
}
public async Task<Order> CreateOrderAsync(Order order)
{
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
using var transaction = connection.BeginTransaction();
try
{
var orderId = await connection.QuerySingleAsync<Guid>(
"INSERT INTO Orders (CustomerId, Total, Status, CreatedAt) " +
"OUTPUT INSERTED.OrderId " +
"VALUES (@CustomerId, @Total, @Status, @CreatedAt)",
order, transaction);
foreach (var item in order.Items)
{
await connection.ExecuteAsync(
"INSERT INTO OrderItems (OrderId, ProductId, Quantity, Price) " +
"VALUES (@OrderId, @ProductId, @Quantity, @Price)",
new { OrderId = orderId, item.ProductId, item.Quantity, item.Price },
transaction);
}
transaction.Commit();
order.Id = orderId;
return order;
}
catch
{
transaction.Rollback();
throw;
}
}
}PostgreSQL
O que é: Sistema de banco de dados relacional open-source avançado.
Características:
- ACID compliance
- Suporte a JSON nativo
- Arrays nativos
- Extensibilidade (extensions)
- Full-text search
- Geospatial data (PostGIS)
- Replicação assíncrona
Benefícios:
- Gratuito e open-source
- Muito robusto e confiável
- Excelente para dados complexos
- Suporte a múltiplos tipos de dados
- Comunidade ativa
Performance:
- Leitura: Excelente com índices adequados
- Escrita: Muito boa para OLTP
- Escalabilidade: Horizontal e vertical
- Concorrência: MVCC (Multi-Version Concurrency Control)
Casos de Uso:
- Aplicações web modernas
- Sistemas com dados geográficos
- Aplicações com dados JSON
- Data warehousing
- Sistemas que precisam de flexibilidade
// Exemplo: Conexão com PostgreSQL
public class PostgreSqlRepository
{
private readonly string _connectionString;
public PostgreSqlRepository(string connectionString)
{
_connectionString = connectionString;
}
public async Task<List<Order>> GetOrdersWithJsonAsync()
{
using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync();
var sql = @"
SELECT o.order_id, o.customer_id, o.total, o.status, o.created_at,
o.metadata::json as Metadata,
c.name as customer_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
WHERE o.status = @Status
ORDER BY o.created_at DESC";
var orders = await connection.QueryAsync<Order>(sql, new { Status = "Active" });
return orders.ToList();
}
public async Task<Order> CreateOrderWithJsonAsync(Order order)
{
using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync();
var sql = @"
INSERT INTO orders (customer_id, total, status, created_at, metadata)
VALUES (@CustomerId, @Total, @Status, @CreatedAt, @Metadata::json)
RETURNING order_id";
var orderId = await connection.QuerySingleAsync<Guid>(sql, new
{
order.CustomerId,
order.Total,
order.Status,
CreatedAt = DateTime.UtcNow,
Metadata = JsonSerializer.Serialize(order.Metadata)
});
order.Id = orderId;
return order;
}
}MySQL
O que é: Sistema de banco de dados relacional open-source popular.
Características:
- ACID compliance
- Múltiplos storage engines (InnoDB, MyISAM)
- Replicação master-slave
- Partitioning
- Full-text search
- Triggers e stored procedures
Benefícios:
- Muito popular e bem documentado
- Fácil de usar e administrar
- Boa performance para leitura
- Suporte a múltiplas plataformas
- Comunidade grande
Performance:
- Leitura: Excelente (especialmente MyISAM)
- Escrita: Boa com InnoDB
- Escalabilidade: Vertical e horizontal
- Concorrência: Row-level locking (InnoDB)
Casos de Uso:
- Aplicações web
- Sistemas de conteúdo
- E-commerce
- Aplicações que precisam de alta performance de leitura
- Sistemas com orçamento limitado
// Exemplo: Conexão com MySQL
public class MySqlRepository
{
private readonly string _connectionString;
public MySqlRepository(string connectionString)
{
_connectionString = connectionString;
}
public async Task<List<Order>> GetOrdersAsync()
{
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
var sql = @"
SELECT o.order_id, o.customer_id, o.total, o.status, o.created_at,
c.name as customer_name
FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id
WHERE o.status = @Status
ORDER BY o.created_at DESC";
var orders = await connection.QueryAsync<Order>(sql, new { Status = "Active" });
return orders.ToList();
}
}Oracle Database
O que é: Sistema de banco de dados relacional enterprise da Oracle.
Características:
- ACID compliance
- RAC (Real Application Clusters)
- Data Guard
- Partitioning avançado
- Materialized views
- PL/SQL
- Flashback technology
Benefícios:
- Muito robusto e confiável
- Excelente para aplicações enterprise
- Recursos avançados de segurança
- Suporte 24/7
- Ferramentas completas
Performance:
- Leitura: Excelente com otimizações
- Escrita: Muito boa
- Escalabilidade: Horizontal e vertical
- Concorrência: Row-level locking
Casos de Uso:
- Aplicações enterprise
- Sistemas financeiros
- Data warehousing
- Aplicações que precisam de alta disponibilidade
- Sistemas com requisitos de compliance rigorosos
📊 Bancos de Dados Não Relacionais (NoSQL)
MongoDB (Document Store)
O que é: Banco de dados de documentos orientado a documentos.
Características:
- Schema flexível
- Suporte nativo a JSON
- Índices em arrays e subdocumentos
- Aggregation pipeline
- Sharding horizontal
- Replicação
Benefícios:
- Flexibilidade de schema
- Fácil de usar com JSON
- Escalabilidade horizontal
- Performance para leitura
- Suporte a geospatial queries
Performance:
- Leitura: Excelente com índices adequados
- Escrita: Boa
- Escalabilidade: Horizontal (sharding)
- Concorrência: Document-level locking
Casos de Uso:
- Aplicações com dados semi-estruturados
- Sistemas de conteúdo
- Logs e analytics
- Aplicações que precisam de flexibilidade de schema
- Sistemas com dados JSON complexos
// Exemplo: Conexão com MongoDB
public class MongoDbRepository
{
private readonly IMongoCollection<Order> _ordersCollection;
public MongoDbRepository(IMongoDatabase database)
{
_ordersCollection = database.GetCollection<Order>("orders");
}
public async Task<List<Order>> GetOrdersAsync()
{
var filter = Builders<Order>.Filter.Eq(o => o.Status, "Active");
var sort = Builders<Order>.Sort.Descending(o => o.CreatedAt);
return await _ordersCollection
.Find(filter)
.Sort(sort)
.ToListAsync();
}
public async Task<Order> CreateOrderAsync(Order order)
{
order.Id = Guid.NewGuid().ToString();
order.CreatedAt = DateTime.UtcNow;
await _ordersCollection.InsertOneAsync(order);
return order;
}
public async Task<List<Order>> GetOrdersByCustomerAsync(string customerId)
{
var filter = Builders<Order>.Filter.Eq(o => o.CustomerId, customerId);
return await _ordersCollection
.Find(filter)
.SortByDescending(o => o.CreatedAt)
.ToListAsync();
}
public async Task UpdateOrderStatusAsync(string orderId, string status)
{
var filter = Builders<Order>.Filter.Eq(o => o.Id, orderId);
var update = Builders<Order>.Update
.Set(o => o.Status, status)
.Set(o => o.UpdatedAt, DateTime.UtcNow);
await _ordersCollection.UpdateOneAsync(filter, update);
}
}Redis (Key-Value Store)
O que é: Banco de dados em memória de chave-valor.
Características:
- Armazenamento em memória
- Múltiplos tipos de dados
- Pub/Sub messaging
- Lua scripting
- Persistência opcional
- Cluster mode
Benefícios:
- Performance extremamente alta
- Baixa latência
- Múltiplos tipos de dados
- Funcionalidades avançadas (pub/sub, Lua)
- Fácil de usar
Performance:
- Leitura: Extremamente rápida (memória)
- Escrita: Muito rápida
- Escalabilidade: Horizontal (cluster)
- Concorrência: Single-threaded (por shard)
Casos de Uso:
- Cache de aplicação
- Session storage
- Rate limiting
- Real-time analytics
- Message queues
- Leaderboards
// Exemplo: Cache com Redis
public class RedisCacheService
{
private readonly ConnectionMultiplexer _redis;
private readonly IDatabase _database;
public RedisCacheService(string connectionString)
{
_redis = ConnectionMultiplexer.Connect(connectionString);
_database = _redis.GetDatabase();
}
public async Task<T> GetAsync<T>(string key)
{
var value = await _database.StringGetAsync(key);
if (value.IsNull)
return default(T);
return JsonSerializer.Deserialize<T>(value);
}
public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
{
var serializedValue = JsonSerializer.Serialize(value);
await _database.StringSetAsync(key, serializedValue, expiry);
}
public async Task<bool> DeleteAsync(string key)
{
return await _database.KeyDeleteAsync(key);
}
public async Task IncrementAsync(string key, long value = 1)
{
await _database.StringIncrementAsync(key, value);
}
public async Task AddToSetAsync(string key, string value)
{
await _database.SetAddAsync(key, value);
}
public async Task<List<string>> GetSetMembersAsync(string key)
{
var values = await _database.SetMembersAsync(key);
return values.Select(v => v.ToString()).ToList();
}
}Cassandra (Wide Column Store)
O que é: Banco de dados distribuído de colunas largas.
Características:
- Distribuído por design
- Linear scalability
- High availability
- Tunable consistency
- CQL (Cassandra Query Language)
- Materialized views
Benefícios:
- Escalabilidade linear
- Alta disponibilidade
- Performance para escrita
- Sem single point of failure
- Flexibilidade de schema
Performance:
- Leitura: Boa para queries por partition key
- Escrita: Excelente
- Escalabilidade: Horizontal (linear)
- Concorrência: Row-level
Casos de Uso:
- Time-series data
- IoT applications
- Analytics
- Sistemas que precisam de alta disponibilidade
- Aplicações com muitas escritas
// Exemplo: Conexão com Cassandra
public class CassandraRepository
{
private readonly ISession _session;
public CassandraRepository(ISession session)
{
_session = session;
}
public async Task<List<Order>> GetOrdersByCustomerAsync(string customerId)
{
var statement = _session.Prepare(
"SELECT order_id, customer_id, total, status, created_at " +
"FROM orders_by_customer " +
"WHERE customer_id = ? " +
"ORDER BY created_at DESC");
var boundStatement = statement.Bind(customerId);
var result = await _session.ExecuteAsync(boundStatement);
return result.Select(row => new Order
{
Id = row.GetValue<string>("order_id"),
CustomerId = row.GetValue<string>("customer_id"),
Total = row.GetValue<decimal>("total"),
Status = row.GetValue<string>("status"),
CreatedAt = row.GetValue<DateTime>("created_at")
}).ToList();
}
public async Task CreateOrderAsync(Order order)
{
var statement = _session.Prepare(
"INSERT INTO orders_by_customer (customer_id, created_at, order_id, total, status) " +
"VALUES (?, ?, ?, ?, ?)");
var boundStatement = statement.Bind(
order.CustomerId,
order.CreatedAt,
order.Id,
order.Total,
order.Status);
await _session.ExecuteAsync(boundStatement);
}
}Neo4j (Graph Database)
O que é: Banco de dados de grafos nativo.
Características:
- Modelagem de relacionamentos
- Cypher query language
- Graph algorithms
- ACID compliance
- Index-free adjacency
- Traversal otimizado
Benefícios:
- Excelente para relacionamentos complexos
- Queries de relacionamento muito rápidas
- Modelagem natural para redes sociais
- Cypher é intuitivo
- Performance para traversals
Performance:
- Leitura: Excelente para relacionamentos
- Escrita: Boa
- Escalabilidade: Vertical
- Concorrência: Row-level
Casos de Uso:
- Redes sociais
- Sistemas de recomendação
- Fraud detection
- Knowledge graphs
- Supply chain management
- Análise de relacionamentos
// Exemplo: Conexão com Neo4j
public class Neo4jRepository
{
private readonly IDriver _driver;
public Neo4jRepository(IDriver driver)
{
_driver = driver;
}
public async Task<List<Customer>> GetCustomerRecommendationsAsync(string customerId)
{
using var session = _driver.AsyncSession();
var query = @"
MATCH (c:Customer {id: $customerId})-[:PURCHASED]->(p:Product)
MATCH (other:Customer)-[:PURCHASED]->(p)
WHERE other.id <> $customerId
WITH other, count(p) as commonProducts
ORDER BY commonProducts DESC
LIMIT 10
RETURN other.id as id, other.name as name, commonProducts";
var result = await session.RunAsync(query, new { customerId });
var customers = new List<Customer>();
await foreach (var record in result)
{
customers.Add(new Customer
{
Id = record["id"].As<string>(),
Name = record["name"].As<string>()
});
}
return customers;
}
public async Task CreateCustomerAsync(Customer customer)
{
using var session = _driver.AsyncSession();
var query = "CREATE (c:Customer {id: $id, name: $name, email: $email})";
await session.RunAsync(query, new
{
customer.Id,
customer.Name,
customer.Email
});
}
public async Task CreatePurchaseRelationshipAsync(string customerId, string productId)
{
using var session = _driver.AsyncSession();
var query = @"
MATCH (c:Customer {id: $customerId})
MATCH (p:Product {id: $productId})
CREATE (c)-[:PURCHASED {date: datetime()}]->(p)";
await session.RunAsync(query, new { customerId, productId });
}
}📈 Comparação de Performance
| Banco de Dados | Tipo | Leitura | Escrita | Escalabilidade | Complexidade |
|---|---|---|---|---|---|
| SQL Server | Relacional | Excelente | Boa | Vertical | Média |
| PostgreSQL | Relacional | Excelente | Muito Boa | Horizontal/Vertical | Média |
| MySQL | Relacional | Excelente | Boa | Horizontal/Vertical | Baixa |
| Oracle | Relacional | Excelente | Muito Boa | Horizontal/Vertical | Alta |
| MongoDB | Document | Excelente | Boa | Horizontal | Baixa |
| Redis | Key-Value | Extremamente Rápida | Muito Rápida | Horizontal | Baixa |
| Cassandra | Wide Column | Boa | Excelente | Horizontal | Média |
| Neo4j | Graph | Excelente (relacionamentos) | Boa | Vertical | Média |
🎯 Critérios de Seleção
Quando usar Relacional:
- Dados estruturados e consistentes
- Transações ACID complexas
- Relacionamentos entre entidades
- Relatórios e analytics complexos
- Integridade referencial importante
- Aplicações enterprise
Quando usar NoSQL:
- Dados semi-estruturados ou não estruturados
- Escalabilidade horizontal necessária
- Flexibilidade de schema
- Performance de leitura crítica
- Dados em tempo real
- Aplicações modernas e ágeis
Quando usar Document Store (MongoDB):
- Dados JSON complexos
- Schema flexível
- Aplicações web modernas
- Content management
- Logs e analytics
Quando usar Key-Value (Redis):
- Cache de aplicação
- Session storage
- Rate limiting
- Real-time features
- Message queues
Quando usar Wide Column (Cassandra):
- Time-series data
- IoT applications
- Alta disponibilidade necessária
- Muitas escritas
- Escalabilidade linear
Quando usar Graph (Neo4j):
- Relacionamentos complexos
- Redes sociais
- Sistemas de recomendação
- Fraud detection
- Knowledge graphs
⚠️ Considerações Importantes
Segurança
- Encryption: Dados em trânsito e em repouso
- Authentication: Controle de acesso
- Authorization: Permissões granulares
- Audit: Logs de acesso e mudanças
Backup e Recovery
- Backup automático: Configurar backups regulares
- Point-in-time recovery: Recuperação até momento específico
- Disaster recovery: Estratégias de DR
- Testing: Testar restauração regularmente
Monitoramento
- Performance metrics: Query performance
- Resource utilization: CPU, memória, disco
- Connection pooling: Gerenciar conexões
- Slow queries: Identificar e otimizar
Manutenção
- Indexing strategy: Índices adequados
- Query optimization: Otimizar queries
- Partitioning: Para grandes volumes
- Archiving: Estratégias de arquivamento
📚 Recursos Adicionais
Ferramentas
- SQL Server: SSMS, Profiler, Data Tools
- PostgreSQL: pgAdmin, DBeaver
- MySQL: MySQL Workbench, phpMyAdmin
- MongoDB: MongoDB Compass, Studio 3T
- Redis: RedisInsight, Redis Commander
- Neo4j: Neo4j Browser, Bloom
ORM e Drivers
- Entity Framework: Para SQL Server
- Npgsql: Para PostgreSQL
- MySqlConnector: Para MySQL
- MongoDB.Driver: Para MongoDB
- StackExchange.Redis: Para Redis
- Neo4j.Driver: Para Neo4j
Livros Recomendados
- "Designing Data-Intensive Applications"
- "Database Design for Mere Mortals"
- "MongoDB: The Definitive Guide"
- "Redis in Action"
- "Graph Databases"