Enfoque Database-Centric
Database-Centric es la decisión de arquitectura que gobierna todo el proyecto: la lógica de negocio no vive en el código de aplicación, vive en el motor de base de datos.
La regla, sin excepciones
Validación, cálculos, asignación de permisos y auditoría se implementan como Stored Procedures, Vistas y Funciones en SQL Server. El backend en C# solo:
- Autentica al usuario (o valida su API key).
- Valida que el request tenga la forma correcta (tipos, campos requeridos).
- Aplica rate limiting.
- Invoca un Stored Procedure con parámetros.
- Mapea el resultado del SP a una respuesta HTTP.
Nunca decide una regla de negocio en C#. Si una decisión requiere lógica ("¿puede este usuario crear otra base?", "¿cuál es su cuota?", "¿este nombre ya existe?"), esa decisión ocurre dentro del SP, no antes.
No hay SQL concatenado por string en ningún lugar del proyecto — cada llamada a base de datos es una invocación parametrizada de un Stored Procedure. Esto elimina por diseño toda una clase de vulnerabilidades de inyección SQL, no como una mitigación agregada después, sino como consecuencia directa de cómo está estructurado el acceso a datos.
Por qué esta decisión, no otra
- Auditable en un solo lugar. Cualquier cambio de estado (crear una base, rotar una contraseña, dar de baja un registro) pasa por un SP, así que el historial de auditoría vive junto a la lógica que lo genera, no disperso en logs de aplicación.
- El backend es reemplazable. Como el backend no toma ninguna decisión de negocio, en teoría podría reescribirse en otro lenguaje sin tocar una sola regla — todas siguen viviendo en la base de datos.
- Menos superficie de error humano. Una regla escrita una sola vez en un SP no puede divergir entre dos endpoints distintos que la reimplementen ligeramente distinto en C#.
Cómo se ve en la práctica
POST /provisioning/crear
│
▼
ProvisioningController — valida que el usuario esté autenticado, aplica rate limit
│
▼
IProvisioningRepository.CrearAsync(usuarioId)
│
▼
sp_AprovisionarBaseDatos
│ - valida que el usuario no supere su cuota de bases activas
│ - genera el nombre de base/usuario únicos
│ - registra el estado inicial "pendiente"
│ - escribe la auditoría
▼
resultado → el backend lo usa para llamar al motor MySQL real y confirmar el aprovisionamiento
Toda la parte marcada como "valida / genera / registra / audita" ocurre dentro del SP — el controller nunca ve esas reglas, solo el resultado final.
Seguí con Patrones de Backend para cómo el código C# está organizado para respetar esta regla de forma consistente.