Librería de acceso a datos moderna y extensible. Actúa como el motor de ejecución para los scripts generados por Quantum.Data.SqlBuilder, proporcionando una interfaz unificada para SQL Server y servicios web ASMX heredados.
$ dotnet add package Quantum.Data.ExecutorQuantum.Data.Executor es una librería de acceso a datos moderna, flexible y extensible para .NET. Actúa como el motor de ejecución para los scripts generados por Quantum.Data.SqlBuilder, proporcionando una interfaz unificada para interactuar con múltiples fuentes de datos, incluyendo SQL Server directo y servicios web ASMX heredados.
IDataExecutor común y una factoría para crear el ejecutor correcto (SQL, Advance, CRM, CRMERP) en tiempo de ejecución.appsettings.json en tiempo de ejecución.Esta librería está diseñada para manejar secretos (como claves de API y de descifrado) y contiene lógica de validación de licencia. Debido a que el código .NET puede ser decompilado, es crítico y obligatorio ofuscar la DLL de Quantum.Data.Executor antes de distribuirla.
La ofuscación modifica el código compilado para hacerlo extremadamente difícil de entender para un ser humano, protegiendo así tus secretos y tu propiedad intelectual. Se recomienda usar herramientas como Obfuscar (código abierto) para proteger las clases internas de configuración y licenciamiento.
Esta librería está diseñada para trabajar en conjunto con Quantum.Data.SqlBuilder.
dotnet add package Quantum.Data.Executor --version 1.0.0
dotnet add package Quantum.Data.SqlBuilder --version 1.0.0
El uso de la librería se centra en la configuración inicial a través de la inyección de dependencias en Program.cs.
appsettings.json{
"ConnectionStrings": {
"DefaultConnection": "Server=...;Database=...;"
},
"ExecutorSettings": {
"ConfigSecretKey": "tu_clave_secreta_aqui", // Usar Secret Manager en desarrollo
"LicenseKey": "el_nombre_cifrado_de_tu_app_aqui",
"Advance": {
"NodeKey": "valor_cifrado_de_la_nodekey"
},
"CRM": {
"SecurityKey": "valor_cifrado_de_la_securitykey"
},
"Binding": { // Opcional: para personalizar timeouts
"ReceiveTimeoutMinutes": 15
}
}
}
Program.csusing Quantum.Data.Executor.Licensing;
using Quantum.Data.Executor.Configuration;
using Quantum.Data.Executor;
using Quantum.Data.SqlBuilder;
// --- INICIO DE LA CONFIGURACIÓN DE QUANTUM ---
// 1. Leer la clave secreta y crear el descifrador.
string configKey = builder.Configuration["ExecutorSettings:ConfigSecretKey"]
?? throw new InvalidOperationException("La clave secreta 'ConfigSecretKey' no se encontró.");
var decryptor = new ConfigurationDecryptor(configKey);
// 2. Validar la licencia de la librería ANTES de continuar.
string licenseKey = builder.Configuration["ExecutorSettings:LicenseKey"];
QuantumLicenseValidator.Validate(licenseKey, decryptor);
var builder = WebApplication.CreateBuilder(args);
// 3. Crear y configurar la factoría de forma modular.
var executorFactory = new ExecutorFactory(decryptor);
// Cargar configuraciones (valores permanecen cifrados).
var advanceSettings = builder.Configuration.GetSection("ExecutorSettings:Advance").Get<AdvanceSettings>();
var crmSettings = builder.Configuration.GetSection("ExecutorSettings:CRM").Get<CrmSettings>();
var bindingSettings = builder.Configuration.GetSection("ExecutorSettings:Binding").Get<BindingSettings>();
// Habilitar los ejecutores que esta aplicación necesita.
executorFactory.AddDirectSqlSupport();
if (advanceSettings != null) executorFactory.AddAdvanceSupport(advanceSettings);
if (crmSettings != null) executorFactory.AddCrmSupport(crmSettings);
if (bindingSettings != null) executorFactory.ConfigureAsmxBindings(bindingSettings);
// 4. Registrar los servicios para la Inyección de Dependencias.
builder.Services.AddSingleton<IExecutorFactory>(executorFactory);
builder.Services.AddTransient<SqlBuilder>();
// --- FIN ---
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
private readonly IExecutorFactory _factory;
private readonly SqlBuilder _builder;
public DataController(IExecutorFactory factory, SqlBuilder builder)
{
_factory = factory;
_builder = builder;
}
// --- EJEMPLO: SQL DIRECTO ---
[HttpGet("sql/products")]
public async Task<IActionResult> GetProductsFromSql([FromServices] IConfiguration config)
{
var command = _builder.Select("*").From("Products").Build();
var executor = _factory.CreateDirectSqlExecutor(config.GetConnectionString("DefaultConnection")!);
DataSet result = await executor.GetDataSetAsync(command);
return Ok(result.Tables[0]);
}
// --- EJEMPLO: ADVANCE (CON LOGIN) ---
[HttpGet("advance/customers/{node}")]
public async Task<IActionResult> GetCustomersFromAdvance(string node)
{
// La factoría se encarga de buscar la URL.
var executor = await _factory.CreateAdvanceExecutorAsync(node);
if (executor is not AdvanceAsmxExecutor advanceExecutor)
return StatusCode(500, "El ejecutor no es de tipo Advance.");
// La aplicación controla el flujo de login.
bool loginOk = await advanceExecutor.LoginAsync("empresa_ejemplo", "usuario", "clave");
if (!loginOk)
return Unauthorized("Login en Advance falló.");
var command = _builder.Select("Id, Nombre").From("Clientes").Build();
DataSet result = await executor.GetDataSetAsync(command);
return Ok(result.Tables[0]);
}
}
Este proyecto está licenciado bajo la Licencia MIT. Ver el archivo LICENSE para más detalles.