Files
Plataforma-de-desarrolladores/AGENTS_STORED_PROCEDURES.md
Jorge Luis caudillo esparza 8f33c860ec Ajustes
2026-08-13 19:46:33 -07:00

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, DELETE ni MERGE directamente 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>.
  • PA significa 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 ejemplo Add, Update, List, Activate, Deactivate o Delete.
  • Ejemplos: PA_Sis_UsuarioAdd, PA_Sis_UsuarioUpdate, PA_Sis_UsuarioList, PA_Sis_UsuarioActivate, PA_Sis_UsuarioDeactivate y PA_Sis_UsuarioDelete.

Parámetros y resultado obligatorios

Todos los procedimientos deben declarar:

@CveUsuarioEjecuta int,
@ErrorMostrar varchar(max) OUTPUT,
@ErrorTipo int OUTPUT,
@Return bit OUTPUT
  • @CveUsuarioEjecuta identifica al usuario autenticado que ejecuta la operación.
  • Al inicio, establecer @ErrorMostrar = NULL, @ErrorTipo = 0 y @Return = 0.
  • Establecer @Return = 1 únicamente cuando la operación termine correctamente.
  • @ErrorTipo = 0: sin error ni advertencia.
  • @ErrorTipo = 1: error.
  • @ErrorTipo = 2: advertencia.
  • @ErrorMostrar contiene 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 ON y TRY/CATCH en todos los procedimientos.
  • Los procedimientos no deben usar SET XACT_ABORT ON, BEGIN TRANSACTION, COMMIT TRANSACTION, ROLLBACK TRANSACTION ni modificar una transacción recibida.
  • La transacción pertenece a la capa de servicio en C#, que debe usar TransactionLogic dentro de using al coordinar las llamadas a repositorios.
  • El servicio llama Commit() solamente cuando todas las operaciones requeridas terminan correctamente. Un fallo, excepción o salida sin Commit() debe permitir que Dispose() 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 EXISTS en lugar de COUNT(*).
  • En CATCH, generar un mensaje técnico separado con ERROR_NUMBER(), ERROR_PROCEDURE(), ERROR_LINE() y ERROR_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 Borrado ni FechaBorrado; no deben agregarse a tablas, modelos, consultas ni procedimientos nuevos.
  • Las operaciones de eliminación deben usar DELETE fí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 = 2 y 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 DELETE directamente.

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.