Introducción
Al hace uso de linq con objetos se presenta un problema ya que no se resuelve de forma correcta la comparaciones entre entidades, esto se debe al hacer uso de un objeto el mismo se compara por medio de la referencia (o sea del puntero en memoria de la instancia de la entidad) y no su contenido
Si se usara tipos simples no se tendría este inconveniente ya que las comparaciones se harían por valor, pero al ser objetos se usa la referencia, es por eso que se será necesario indicar mediante alguna técnica como comparar las entidades.
Para el ejemplo se trabajara con una lista de artículos, declarando una clase del estilo
public class ArticuloBase { public int Id { get; set; } public string Nombre { get; set; } public int Stock { get; set; } public decimal Precio { get; set; } }
el contenido de las listas tendrá ítems duplicados, aplicando las diferentes técnicas se podría usar linq directamente con los objetos de la lista.
Distinct
Si usamos distinct de linq sobre una lista para evitar duplicados no obtendremos efecto alguno
ya que la lista resultante sigue teniendo 4 ítems, cuando debería haber detectado duplicados, para solucionar el problema será necesario definir como es que la entidad debe ser comparada
La primer opción será por medio de un comparador, se define una clase que implemente IEqualityComparer<>
public class ArticuloComparer : IEqualityComparer<ArticuloBase> { public bool Equals(ArticuloBase x, ArticuloBase y) { return x.Id == y.Id; } public int GetHashCode(ArticuloBase obj) { return obj.Id.GetHashCode(); } }
esto hace que al usarse como parte del distinct permita conocer que entidades deben ser iguales
ahora si se detecto el ítem duplicado y solo se obtiene como resultado 3, es necesario remarcar que en la clase se definio que compara por id, por lo que un diferente stock será descartado.
Existe otra opción valida cuando se usan entidades la cual consiste en implementar la interfaz IEquatable<>, en este caso se definió una clase heredada para separa la implementación y poder testear, pero se podría haber unido todo en una única clase
public class Articulo : IEquatable<Articulo> { public int Id { get; set; } public string Nombre { get; set; } public int Stock { get; set; } public decimal Precio { get; set; } #region IEquatable<Articulo> Members public bool Equals(Articulo other) { if (Object.ReferenceEquals(other, null)) return false; if (Object.ReferenceEquals(this, other)) return true; return this.Id.Equals(other.Id); } public override int GetHashCode() { int hashDescription = this.Id == null ? 0 : this.Id.GetHashCode(); return hashDescription; } #endregion }
con esta otra forma se obtiene el mismo resultado
Group by
Al usar el group by de linq se presentan los mismo problemas que el distinct, la entidad no puede resolver como debe agrupar cada entidad
Pero si lo indicamos por medio del IEquatable<>, en ese caso podra reconocer cual, o cuales, propiedades una entidad es igual a otra
El articulo 2 ahora si se agrupa y suma su stock
Código
[C#]
|
Siempre dandome una solucion!! Gracias Leandro..!!
ResponderEliminarSaludos.