Created
March 29, 2025 19:57
-
-
Save alandalegend/a20d2ded71d53f70100cbb3bb653bc25 to your computer and use it in GitHub Desktop.
Identificar registros duplicados en XAF Listview Blazor DevExpress
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Hola, esta clase es para detectar duplicados visualmente en el listview de nuestro proyecto de Blazor en XAF / DevExpress | |
Ayuda a que sea para diversas propiedades, es reutilizable, centralizado, se usa el caché de la sesión para | |
evitar consultar la BD en cada refresh, y se tiene una funcionalidad de que se borré el caché cuando | |
algun coolaborador actualice algún registro | |
Puntos en este módulo: | |
🔧 1. Clase DuplicadoHelper.cs | |
🧬 2. Cómo usarlo en cualquier clase XPO (por ejemplo Servidor) | |
🎨 3. Usa Appearance para aplicar color visual | |
🔁 4. Limpieza automática del cache después de guardar (en Module.cs) | |
✅ Resultado Final | |
Bien... iniciemos con el código | |
*/ | |
/* | |
🔧 1. Clase DuplicadoHelper.cs | |
*/ | |
using DevExpress.Xpo; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.CompilerServices; | |
public static class DuplicadoHelper | |
{ | |
// Cache de duplicados por propiedad y sesión | |
private static readonly ConditionalWeakTable<Session, Dictionary<string, HashSet<object>>> _cache = | |
new ConditionalWeakTable<Session, Dictionary<string, HashSet<object>>>(); | |
/// <summary> | |
/// Determina si el valor de una propiedad está duplicado dentro de la entidad. | |
/// </summary> | |
public static bool EsDuplicado<T>(Session session, string nombrePropiedad, object valor) where T : DevExpress.Xpo.BaseObject | |
{ | |
if (session == null || valor == null) | |
return false; | |
if (!_cache.TryGetValue(session, out var duplicadosPorPropiedad)) | |
{ | |
duplicadosPorPropiedad = new Dictionary<string, HashSet<object>>(); | |
_cache.Add(session, duplicadosPorPropiedad); | |
} | |
var clave = $"{typeof(T).FullName}.{nombrePropiedad}"; | |
if (!duplicadosPorPropiedad.TryGetValue(clave, out var duplicados)) | |
{ | |
var todos = new XPCollection<T>(session); | |
duplicados = todos | |
.GroupBy(x => | |
{ | |
var prop = typeof(T).GetProperty(nombrePropiedad); | |
return prop?.GetValue(x); | |
}) | |
.Where(g => g.Count() > 1) | |
.Select(g => g.Key) | |
.ToHashSet(); | |
duplicadosPorPropiedad[clave] = duplicados; | |
} | |
return duplicados.Contains(valor); | |
} | |
/// <summary> | |
/// Limpia el cache de duplicados cuando se hace commit de una transacción. | |
/// </summary> | |
public static void LimpiarCache(Session session) | |
{ | |
_cache.Remove(session); | |
} | |
} | |
/* | |
🧬 2. Cómo usarlo en cualquier clase XPO (por ejemplo Servidor.cs) | |
*/ | |
public class Servidor : BaseObject | |
{ | |
/*..... todas tus demás propiedades*/ | |
//Aquí validaremos la propiedad VMName | |
[NonPersistent] | |
public bool VMNameDuplicado => | |
DuplicadoHelper.EsDuplicado<Servidor>(this.Session as Session, nameof(VMName), VMName); | |
//Aquí validaremos la propiedad IpInterna | |
[NonPersistent] | |
public bool IpDuplicada => | |
DuplicadoHelper.EsDuplicado<Servidor>(this.Session as Session, nameof(IpInterna), IpInterna); | |
} | |
/* | |
🎨 3. Usa Appearance para aplicar color visual | |
*/ | |
[Appearance("VMNameDuplicada", TargetItems = "VMName", Criteria = "VMNameDuplicado = true", | |
Context = "ListView", FontColor = "Red", BackColor = "#FFE5E5", Priority = 1)] | |
[Appearance("IpInternaDuplicada", TargetItems = "IpInterna", Criteria = "IpDuplicada = true", | |
Context = "ListView", FontColor = "Red", BackColor = "#FFE5E5", Priority = 1)] | |
/* | |
🔁 4. Limpieza automática del cache después de guardar (en Module.cs) | |
*/ | |
public override void Setup(XafApplication application) | |
{ | |
base.Setup(application); | |
application.ObjectSpaceCreated += (sender, e) => | |
{ | |
if (e.ObjectSpace is DevExpress.ExpressApp.Xpo.XPObjectSpace xp) | |
{ | |
var session = xp.Session; | |
if (!session.IsObjectsLoading) | |
{ | |
session.AfterCommitTransaction += (s, args) => | |
{ | |
DuplicadoHelper.LimpiarCache(session); | |
}; | |
} | |
} | |
}; | |
} | |
/* | |
✅ Resultado Final | |
♻️ Reutilizable Solo cambias el nombre del campo | |
⚡ Rápido Evalúa duplicados una sola vez por sesión | |
🧼 Limpieza automática Al guardar cambios | |
🔒 No se guarda en la BD Propiedades [NonPersistent] | |
🎯 Compatible Funciona perfecto con Blazor y XPO | |
PD: todo esto fue realizado gracias a mi amigo personal ChatGPT, | |
Espero les sirva tanto como a mi (y principalmente, les ahorre horas de debuggin) ✌️ | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment