5.5 KiB
5.5 KiB
Reglas obligatorias de procedimientos almacenados
Estas reglas complementan AGENTS.md y son obligatorias para toda consulta nueva o modificada en la aplicación.
Acceso a datos
- Todas las lecturas y escrituras de la aplicación deben usar procedimientos almacenados.
- No escribir
SELECT,INSERT,UPDATE,DELETEniMERGEdirectamente en C# dentro de repositorios, servicios, páginas, controles o la master page. - Los repositorios deben usar
CommandType.StoredProcedure. - Todos los valores proporcionados por la aplicación deben enviarse como parámetros.
- Nunca concatenar entrada del usuario en SQL.
Nombres
- Usar el formato
PA_<Tipo>_<Entidad><Accion>. PAsignifica procedimiento almacenado.<Tipo>identifica el grupo funcional:Sis,Tra,Vta,Conta,Clientes,Fraccionamientos, etcétera.<Entidad>identifica el objeto y<Accion>describe claramente la operación; por ejemploAdd,Update,List,Activate,DeactivateoDelete.- Ejemplos:
PA_Sis_UsuarioAdd,PA_Sis_UsuarioUpdate,PA_Sis_UsuarioList,PA_Sis_UsuarioActivate,PA_Sis_UsuarioDeactivateyPA_Sis_UsuarioDelete.
Parámetros y resultado obligatorios
Todos los procedimientos deben declarar:
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
@CveUsuarioEjecutaidentifica al usuario autenticado que ejecuta la operación.- Al inicio, establecer
@ErrorMostrar = NULL,@ErrorTipo = 0y@Return = 0. - Establecer
@Return = 1únicamente cuando la operación termine correctamente. @ErrorTipo = 0: sin error ni advertencia.@ErrorTipo = 1: error.@ErrorTipo = 2: advertencia.@ErrorMostrarcontiene el mensaje amigable en español que puede mostrarse al usuario.- No devolver contraseñas, hashes, cadenas de conexión, SQL, stack traces ni detalles internos mediante
@ErrorMostrar. - Los procedimientos de consulta pueden devolver un result set, pero también deben poblar los parámetros comunes.
- El repositorio debe convertir los parámetros de salida en un modelo de resultado como
DbResult<T>.
Control de errores
- Usar
SET NOCOUNT ONyTRY/CATCHen todos los procedimientos. - Los procedimientos no deben usar
SET XACT_ABORT ON,BEGIN TRANSACTION,COMMIT TRANSACTION,ROLLBACK TRANSACTIONni modificar una transacción recibida. - La transacción pertenece a la capa de servicio en C#, que debe usar
TransactionLogicdentro deusingal coordinar las llamadas a repositorios. - El servicio llama
Commit()solamente cuando todas las operaciones requeridas terminan correctamente. Un fallo, excepción o salida sinCommit()debe permitir queDispose()revierta la transacción ambiental. - Una validación fallida debe establecer los parámetros de salida y ejecutar
RETURN; no debe continuar la mutación. - Para validar existencia, usar normalmente
EXISTSen lugar deCOUNT(*). - En
CATCH, generar un mensaje técnico separado conERROR_NUMBER(),ERROR_PROCEDURE(),ERROR_LINE()yERROR_MESSAGE()para el log. - El mensaje técnico puede notificarse con severidad informativa para que el ejecutor lo registre, pero nunca debe mostrarse directamente al usuario.
Borrado físico
- La base de datos no utiliza las columnas
BorradoniFechaBorrado; no deben agregarse a tablas, modelos, consultas ni procedimientos nuevos. - Las operaciones de eliminación deben usar
DELETEfísico dentro de un procedimiento almacenado. - Antes de eliminar, validar las relaciones que deban conservarse. Si existen dependencias que impiden la operación, devolver una advertencia controlada con
@ErrorTipo = 2y un mensaje claro. - Las eliminaciones de una entidad con hijos propios deben ejecutarse en orden, desde los hijos hasta el padre. El servicio que invoque el procedimiento debe envolver la operación en una transacción de aplicación.
- No deshabilitar constraints ni eliminar información relacionada que pertenezca a otro proceso únicamente para permitir el
DELETE. - Las páginas ASPX continúan llamando contratos y servicios; nunca deben ejecutar
DELETEdirectamente.
Plantilla requerida
CREATE OR ALTER PROCEDURE [dbo].[PA_Sis_RolAdd]
@Rol varchar(50),
@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT
@ErrorMostrar = NULL,
@ErrorTipo = 0,
@Return = 0;
BEGIN TRY
IF EXISTS
(
SELECT 1
FROM dbo.Sis_Roles
WHERE NombreRol = @Rol
)
BEGIN
SET @ErrorMostrar = CONCAT('El rol ''', @Rol, ''' ya se encuentra registrado.');
SET @ErrorTipo = 2;
RETURN;
END;
INSERT INTO dbo.Sis_Roles
(NombreRol, Activo, FechaCreacion)
VALUES
(@Rol, 1, SYSDATETIME());
SET @Return = 1;
END TRY
BEGIN CATCH
SET @ErrorMostrar = 'Ocurrió un error al agregar el rol; favor de contactar a Sistemas.';
SET @ErrorTipo = 1;
SET @Return = 0;
DECLARE @ErrorTecnico nvarchar(2048) = CONCAT(
'Número: ', ERROR_NUMBER(),
'; Procedimiento: ', COALESCE(ERROR_PROCEDURE(), 'PA_Sis_RolAdd'),
'; Línea: ', ERROR_LINE(),
'; Detalle: ', ERROR_MESSAGE()
);
RAISERROR(N'%s', 10, 1, @ErrorTecnico);
END CATCH;
END;
GO
Aunque un procedimiento ejecute varias escrituras, no debe administrar la transacción. La atomicidad se define en el servicio que coordina los repositorios.