A3.Backend.Persistence
4.1.0
dotnet add package A3.Backend.Persistence --version 4.1.0
NuGet\Install-Package A3.Backend.Persistence -Version 4.1.0
<PackageReference Include="A3.Backend.Persistence" Version="4.1.0" />
<PackageVersion Include="A3.Backend.Persistence" Version="4.1.0" />
<PackageReference Include="A3.Backend.Persistence" />
paket add A3.Backend.Persistence --version 4.1.0
#r "nuget: A3.Backend.Persistence, 4.1.0"
#:package A3.Backend.Persistence@4.1.0
#addin nuget:?package=A3.Backend.Persistence&version=4.1.0
#tool nuget:?package=A3.Backend.Persistence&version=4.1.0
A3.Backend.Persistence
Librería NuGet para acceso a base de datos MySQL del sistema Genie (A3), implementando los patrones Repository y Unit of Work sobre Entity Framework Core 8.
Tabla de contenidos
- Requisitos
- Instalación
- Arquitectura
- Contextos de base de datos
- Registro en DI
- Uso básico
- Conexiones dinámicas (multi-tenant)
- Consultas paralelas
- Referencia de la interfaz Repository
- Modelos por contexto
Requisitos
| Dependencia | Versión |
|---|---|
| .NET | 8.0 |
| Microsoft.EntityFrameworkCore.Tools | 8.0.5 |
| MySql.EntityFrameworkCore | 8.0.5 |
| Newtonsoft.Json | 13.0.3 |
Instalación
dotnet add package A3.Backend.Persistence
Arquitectura
El proyecto expone 6 contextos independientes, cada uno con su propio stack de Repository + UnitOfWork + Factory.
A3.Backend.Persistence
├── Context/
│ ├── Admin/ → GenieAdminContext
│ ├── Operations/ → GenieOperationsContext
│ ├── Templates/ → GenieTemplatesContext
│ ├── DBManager/ → GenieDBManagerContext
│ ├── Registry/ → RegistryContext
│ └── TrxFraud/ → GenieBackendTrxFraudReviewContext
│
├── Models/ → Entidades EF por contexto
│
├── Repository/
│ ├── IUnitOfWorkFactory<TUnitOfWork>
│ ├── Admin/ → IAdminRepository, IAdminUnitOfWork, AdminUnitOfWorkFactory
│ ├── Operations/ → IOperationsRepository, IOperationsUnitOfWork, OperationsUnitOfWorkFactory
│ ├── Templates/ → ITemplatesRepository, ITemplatesUnitOfWork, TemplatesUnitOfWorkFactory
│ ├── DBManager/ → IDbManagerRepository, IDbManagerUnitOfWork, DbManagerUnitOfWorkFactory
│ ├── Registry/ → IRegistryRepository, IRegistryUnitOfWork, RegistryUnitOfWorkFactory
│ └── TrxFraud/ → ITrxFraudRepository, ITrxFraudUnitOfWork, TrxFraudUnitOfWorkFactory
│
└── Utils/
└── Utils.cs → DiffDates(DateTime, DateTime)
Tipos de conexión por contexto
| Contexto | Tipo de conexión | Factory |
|---|---|---|
| Admin | DbContextOptions (estática) |
AdminUnitOfWorkFactory |
| DBManager | DbContextOptions (estática) |
DbManagerUnitOfWorkFactory |
| Registry | DbContextOptions (estática) |
RegistryUnitOfWorkFactory |
| TrxFraud | DbContextOptions (estática) |
TrxFraudUnitOfWorkFactory |
| Operations | string dinámica |
OperationsUnitOfWorkFactory |
| Templates | string dinámica |
TemplatesUnitOfWorkFactory |
OperationsyTemplatesaceptan una connection string en runtime, lo que permite soporte multi-tenant (una BD por cliente).
Contextos de base de datos
| Contexto | Responsabilidad |
|---|---|
GenieAdminContext |
Usuarios, roles, permisos, subproyectos, configuración, catálogos geográficos, dispositivos |
GenieOperationsContext |
Transacciones, invitaciones, personas, enrollments, logs, OTPs, imágenes |
GenieTemplatesContext |
Datos biométricos (templates) |
GenieDBManagerContext |
APIs autorizadas, gestión de bases de datos |
RegistryContext |
Logs de ejecución del registro |
GenieBackendTrxFraudReviewContext |
Revisión de fraude en transacciones |
Registro en DI
Contextos estáticos (Admin, DBManager, Registry, TrxFraud)
using A3.Backend.Persistence.Context.Admin;
using A3.Backend.Persistence.Repository;
using A3.Backend.Persistence.Repository.Admin;
using Microsoft.EntityFrameworkCore;
// Registrar UnitOfWork como Scoped para uso normal
services.AddScoped<IAdminUnitOfWork>(sp =>
{
var optionsBuilder = new DbContextOptionsBuilder<GenieAdminContext>();
optionsBuilder.UseMySQL(configuration.GetConnectionString("AdminConnection"));
return new AdminUnitOfWork(new GenieAdminContext(optionsBuilder.Options));
});
// Registrar Factory como Singleton para uso paralelo
services.AddSingleton<IUnitOfWorkFactory<IAdminUnitOfWork>>(sp =>
{
var optionsBuilder = new DbContextOptionsBuilder<GenieAdminContext>();
optionsBuilder.UseMySQL(configuration.GetConnectionString("AdminConnection"));
return new AdminUnitOfWorkFactory(optionsBuilder.Options);
});
Contextos dinámicos (Operations, Templates)
using A3.Backend.Persistence.Repository.Operations;
// Factory que recibe la connection string en runtime
services.AddTransient<Func<string, IOperationsUnitOfWork>>(sp =>
connectionString => new OperationsUnitOfWork(connectionString));
Uso básico
public class UserService
{
private readonly IAdminUnitOfWork _uow;
public UserService(IAdminUnitOfWork uow) => _uow = uow;
public User? GetById(int id)
=> _uow.Repository<User>().Get(id);
public IEnumerable<User> GetActive()
=> _uow.Repository<User>().Find(u => u.Active == true);
public void Create(User user)
{
_uow.Repository<User>().Add(user);
_uow.Save();
}
public async Task<int> UpdateEmailAsync(int id, string email)
=> _uow.Repository<User>().UpdateRange(
u => u.Id == id,
s => s.SetProperty(u => u.Email, email));
}
Conexiones dinámicas (multi-tenant)
Para Operations y Templates, la connection string se resuelve en runtime por cliente/tenant:
public class TransactionService
{
private readonly Func<string, IOperationsUnitOfWork> _uowFactory;
public TransactionService(Func<string, IOperationsUnitOfWork> uowFactory)
=> _uowFactory = uowFactory;
public Transaction? GetTransaction(string tenantConnectionString, int id)
{
using var uow = _uowFactory(tenantConnectionString);
return uow.Repository<Transaction>().Get(id);
}
}
O directamente con la factory:
var factory = new OperationsUnitOfWorkFactory(tenantConnectionString);
using var uow = factory.Create();
var transactions = uow.Repository<Transaction>().GetAll();
Consultas paralelas
⚠️
DbContextno es thread-safe. Para consultas paralelas siempre usar la Factory para crear un contexto por hilo.
Contextos estáticos
public async Task<List<User>> GetUsersParallelAsync(
IUnitOfWorkFactory<IAdminUnitOfWork> factory,
List<int> ids)
{
var tasks = ids.Select(id => Task.Run(() =>
{
using var uow = factory.Create();
return uow.Repository<User>().Get(id);
}));
return (await Task.WhenAll(tasks)).Where(u => u != null).ToList()!;
}
Contextos dinámicos (multi-tenant en paralelo)
public async Task<Dictionary<string, List<Transaction>>> GetAllTenantsAsync(
Dictionary<string, string> tenantConnections)
{
var tasks = tenantConnections.Select(async kvp =>
{
var factory = new OperationsUnitOfWorkFactory(kvp.Value);
using var uow = factory.Create();
var data = uow.Repository<Transaction>().GetAll().ToList();
return new { Tenant = kvp.Key, Data = data };
});
var results = await Task.WhenAll(tasks);
return results.ToDictionary(r => r.Tenant, r => r.Data);
}
Consultas mixtas (Admin + Operations en paralelo)
public async Task<(User user, List<Transaction> transactions)> GetReportAsync(
IUnitOfWorkFactory<IAdminUnitOfWork> adminFactory,
string operationsConnStr,
int userId)
{
var userTask = Task.Run(() =>
{
using var uow = adminFactory.Create();
return uow.Repository<User>().Get(userId);
});
var trxTask = Task.Run(() =>
{
var factory = new OperationsUnitOfWorkFactory(operationsConnStr);
using var uow = factory.Create();
return uow.Repository<Transaction>().Find(t => t.UserId == userId).ToList();
});
await Task.WhenAll(userTask, trxTask);
return (await userTask, await trxTask);
}
Referencia de la interfaz Repository
Todos los repositorios exponen los mismos métodos base:
| Método | Descripción |
|---|---|
GetAll() |
Retorna todas las entidades |
Get(int id) |
Busca por clave primaria entera |
Get(string name) |
Busca por propiedad Name |
Find(predicate) |
Filtra con expresión lambda |
Find(predicate, includes) |
Filtra con includes de navegación |
Add(entity) |
Agrega una entidad |
AddRange(entities) |
Agrega una lista de entidades |
Update(entity) |
Marca la entidad como modificada |
UpdateRange(predicate, setPropertyCalls) |
Actualización masiva con EF ExecuteUpdate |
Delete(int id) |
Elimina por id |
Delete(predicate) |
Eliminación masiva con EF ExecuteDelete |
Save() |
Persiste los cambios en la BD |
FromSqlRaw(params, sql) |
Ejecuta un stored procedure o SQL raw |
Métodos específicos por contexto
Admin
| Método | Descripción |
|---|---|
JoinGetAssingTech(subCustomerId) |
Técnico asignado con menor carga |
JoinGetScores(subCustomer) |
Scores activos de un subproyecto |
JoinGetScoreById(subprojectId, scoreId) |
Score específico |
JoinGetTransactionsPending(idUser?) |
Transacciones pendientes de revisión |
JoinGetTransactionsByTech() |
Transacciones agrupadas por técnico |
Operations
| Método | Descripción |
|---|---|
JoinGetHistoricSoreById(idTransaction) |
Historial de scores de una transacción |
JoinGetHistoricSoreRejectedById(idTransaction) |
Historial de scores rechazados |
JoinGePersontData(personId, subCustomerId, name) |
Datos completos de una persona |
JoinGetTransactionsByTechOp(trxOrigin, subCustomerId, date) |
Transacciones por técnico en Operations |
Modelos por contexto
<details> <summary><strong>Admin</strong></summary>
User · UserRole · UserBySubcustomer · UserPasswordHistory · UserBlocked · UserSeed · UsersAttribute · LogUserBlocking · Token · ProjectUserActive · RolesBySubCustomer · ModuleRole · SubModuleRole · Module · SubModule · Endpoint · EndpointsByModule · EndpointsBySubModule · Customer · SubProject · Branch · Place · Address · Location · ConfigurationParameter · SubCustomerConfiguration · LockConfiguration · LockoutPeriod · Country · CountriesNew · City · CitiesNew · StatesNew · NumericalCodeCountry · TechnicianBySubProject · AssingTechnician · TransactionPendigReview · Template · TemplateType · IdentificationType · IdentificationTypeBySubproject · CausalRejection · RiskLevel · Permutation · Step · SubStep · PushDataField · PushDataFieldBySubCustomer · ResultDataField · ResultDataFieldBySubCustomer · LookAndFeelFile · TransactionType · TransactionScore · TransactionScoresBySubproject · Device · Middle · AuthorizedPhone · StatePerson · TransactionState · ScoreScript · ScriptGroup
</details>
<details> <summary><strong>Operations</strong></summary>
Invitation · InvitationDevice · InvitationPerson · InvitationStep · InvitationStepConfig · InvitationTemplate · Person · Enrollment · EnrollmentTemplate · Transaction · TransactionImage · TransactionProperty · TransactionReviewScore · Log · LogEvent · LogImage · ServiceLog · ErrorLog · ExecutionsLog · ApplicationAlert · ApplicationAudit · Otp · PendingAction · HistoricQualification · IdentitiesBySubProject · ResponseControlList · ResponseImage · ReviewExtractDataV2 · ReviewRegula · TemporalData · VwInfoTransaction
</details>
<details> <summary><strong>Templates</strong></summary>
BiometricData
</details>
<details> <summary><strong>DBManager</strong></summary>
AuthorizedApi · Database
</details>
<details> <summary><strong>Registry</strong></summary>
ErrorLog · ExecutionLog
</details>
<details> <summary><strong>TrxFraud</strong></summary>
Transaction · DeviceFingerprint · RiskThreshold · ErrorLog
</details>
Configuración MySQL recomendada
{
"ConnectionStrings": {
"AdminConnection": "server=host;database=admin_db;user=usr;password=***;Max Pool Size=100;",
"OperationsConnection": "server=host;database=ops_db;user=usr;password=***;Max Pool Size=50;",
"TemplatesConnection": "server=host;database=tpl_db;user=usr;password=***;Max Pool Size=50;"
}
}
Licencia
Consulta el archivo LICENSE.txt para más información.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- MySql.EntityFrameworkCore (>= 8.0.5)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.1.0 | 38 | 2/27/2026 |
| 4.0.0 | 32 | 2/27/2026 |
| 3.2.50.1 | 101 | 1/27/2026 |
| 3.2.50 | 99 | 1/27/2026 |
| 3.2.49.2 | 100 | 1/13/2026 |
| 3.2.49.1 | 104 | 1/7/2026 |
| 3.2.49 | 97 | 1/7/2026 |
| 3.2.48.44 | 79 | 2/25/2026 |
| 3.2.48.43 | 127 | 2/19/2026 |
| 3.2.48.42 | 171 | 2/4/2026 |
| 3.2.48.41 | 152 | 1/20/2026 |
| 3.2.48.40 | 100 | 1/14/2026 |
| 3.2.48.39 | 104 | 1/8/2026 |
| 3.2.48.38 | 106 | 1/8/2026 |
| 3.2.48.37 | 101 | 1/8/2026 |
| 3.2.48.36 | 191 | 12/12/2025 |
| 3.2.48.35 | 167 | 11/28/2025 |
| 3.2.48.34 | 198 | 11/27/2025 |
| 3.2.48.33 | 260 | 11/24/2025 |
| 3.2.48.32 | 309 | 11/12/2025 |