Initial commit

This commit is contained in:
Jorge Luis caudillo esparza
2026-07-14 11:15:20 -07:00
commit 6685ef63fb
7326 changed files with 1020873 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# Reglas obligatorias de mapeo de resultados
Estas reglas complementan `AGENTS.md` y `AGENTS_STORED_PROCEDURES.md`.
## Extensión estándar
- Todo resultado obtenido con `IDataReader` debe convertirse mediante `AppCode/Utilities/DataReaderExtensions.cs`.
- No repetir bloques manuales como `Propiedad = Convert.ToInt32(reader["Columna"])` en repositorios o servicios.
- Resultados admitidos:
```csharp
T item = reader.ToObject<T>();
List<T> items = reader.ToList<T>();
DataTable table = reader.ToDataTable();
JArray json = reader.ToJsonArray();
```
- `ToObject<T>()` devuelve `null` cuando el procedimiento no devuelve filas.
- `ToList<T>()` devuelve una lista vacía cuando no hay filas; no devuelve `null`.
- `ToDataTable()` devuelve un `DataTable` vacío cuando no hay filas.
- `ToJsonArray()` devuelve un `JArray` vacío cuando no hay filas.
## Operaciones asíncronas
- Para código nuevo, preferir las versiones asíncronas cuando el proveedor exponga `DbCommand` y `DbDataReader`.
- Métodos disponibles: `ToObjectAsync<T>()`, `ToListAsync<T>()`, `ToDataTableAsync()` y `ToJsonArrayAsync()`.
- Los métodos asíncronos deben recibir y propagar un `CancellationToken` cuando la llamada superior disponga de uno.
- Abrir el lector con `ExecuteReaderAsync`; no envolver operaciones síncronas de base de datos en `Task.Run`.
- Usar `ConfigureAwait(false)` dentro de infraestructura, repositorios y servicios que no necesiten el contexto de WebForms.
- Cerrar o desechar el lector antes de leer `@ErrorMostrar`, `@ErrorTipo` y `@Return`.
- Una página WebForms que espere directamente debe declarar `Async="true"` y usar `RegisterAsyncTask` o un evento asíncrono compatible.
- Mantener los métodos síncronos únicamente para flujos existentes que todavía no se hayan migrado de extremo a extremo.
Ejemplo:
```csharp
List<UsuarioModel> usuarios;
using (DbDataReader reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
{
usuarios = await reader.ToListAsync<UsuarioModel>(cancellationToken).ConfigureAwait(false);
}
StoredProcedureCommand.EnsureSuccess(command);
return usuarios;
```
## Convención de columnas y propiedades
- El mapeo se realiza por nombre de columna y propiedad sin distinguir mayúsculas/minúsculas.
- Los procedimientos deben usar alias para que las columnas coincidan con el modelo.
- Cuando no sea posible usar el mismo nombre, decorar la propiedad con `[Column("NombreColumna")]`.
- Las columnas adicionales se ignoran.
- Las propiedades sin columna conservan su valor predeterminado.
- `DBNull` se convierte en `null` para propiedades anulables o de referencia; para propiedades no anulables conserva el valor predeterminado.
- Se admiten tipos anulables, enumeraciones, `Guid`, `TimeSpan`, `DateTimeOffset`, booleanos y conversiones primitivas.
- Una conversión incompatible debe producir una excepción para que `DbExecutor` la registre; no ocultar errores de contrato entre el PA y el modelo.
## Uso correcto con procedimientos almacenados
- El repositorio crea y configura el comando mediante `StoredProcedureCommand`.
- El repositorio abre el lector dentro de `using`.
- Debe cerrar o desechar el lector antes de llamar `StoredProcedureCommand.EnsureSuccess(command)`, porque los parámetros OUTPUT se reciben al finalizar el lector.
- La extensión sólo mapea datos; no abre conexiones, no crea comandos, no captura excepciones y no decide mensajes para el usuario.
- Páginas ASPX, controles y master pages no deben manejar `IDataReader` directamente.
Ejemplo para un objeto:
```csharp
UserModel user;
using (IDataReader reader = command.ExecuteReader())
{
user = reader.ToObject<UserModel>();
}
StoredProcedureCommand.EnsureSuccess(command);
return user;
```
Ejemplo para una lista:
```csharp
List<MenuItemModel> items;
using (IDataReader reader = command.ExecuteReader())
{
items = reader.ToList<MenuItemModel>();
}
StoredProcedureCommand.EnsureSuccess(command);
return items;
```
## Elección del tipo de resultado
- Preferir modelos tipados para reglas de negocio, seguridad, usuarios, permisos, menús y módulos nuevos.
- Usar `DataTable` sólo para compatibilidad con componentes WebForms o migración de código heredado que realmente lo requiera.
- Usar `JArray` únicamente cuando el contrato de salida sea JSON dinámico y no exista un modelo estable.
- No convertir primero a `DataTable` para después crear objetos o JSON; mapear directamente desde `IDataReader`.