Tengo algunas campanas en mi base de datos con el mismo número. Quiero obtenerlos todos sin duplicarlos. Creé una clase de comparación para hacer este trabajo, pero la ejecución de la función provoca un gran retraso de la función sin distinción, ¡de 0,6 segundos a 3,2 segundos!
¿Lo estoy haciendo bien o tengo que usar otro método?
reg.AddRange(
(from a in this.dataContext.reglements
join b in this.dataContext.Clients on a.Id_client equals b.Id
where a.date_v <= datefin && a.date_v >= datedeb
where a.Id_client == b.Id
orderby a.date_v descending
select new Class_reglement
{
nom = b.Nom,
code = b.code,
Numf = a.Numf,
})
.AsEnumerable()
.Distinct(new Compare())
.ToList());
class Compare : IEqualityComparer<Class_reglement>
{
public bool Equals(Class_reglement x, Class_reglement y)
{
if (x.Numf == y.Numf)
{
return true;
}
else { return false; }
}
public int GetHashCode(Class_reglement codeh)
{
return 0;
}
}
c#
linq
iequalitycomparer
Akrem
fuente
fuente
Respuestas:
Su
GetHashCode
implementación siempre devuelve el mismo valor.Distinct
se basa en una buena función hash para funcionar de manera eficiente porque crea internamente una tabla hash .Al implementar interfaces de clases, es importante leer la documentación para saber qué contrato se supone que debe implementar. 1
En su código, la solución es reenviar
GetHashCode
aClass_reglement.Numf.GetHashCode
e implementar de manera adecuada allí.Aparte de eso, su
Equals
método está lleno de código innecesario. Se podría reescribir de la siguiente manera (misma semántica, ¼ del código, más legible):Por último, la
ToList
llamada es innecesaria y requiere mucho tiempo:AddRange
acepta cualquiera,IEnumerable
por lo queList
no es necesaria la conversión a a . TambiénAsEnumerable
es redundante aquí, ya que procesar el resultado provocará esto de todos modos.AddRange
1 Escribir código sin saber lo que realmente hace se llama programación de culto de carga . Es una práctica sorprendentemente extendida. Básicamente no funciona.
fuente
GetHashCode
. Sin embargo, tenga en cuenta que la documentación deIEqualityComparer<T>
no especifica qué hacer con losnull
argumentos, pero los ejemplos proporcionados en el artículo tampoco lo admitennull
.Prueba este código:
Ejemplo de su uso sería
fuente
GetHashCode
también necesita usar la expresión:return _expr.Invoke(obj).GetHashCode();
consulte esta publicación para conocer su uso.Solo código, con implementación
GetHashCode
yNULL
validación:Ejemplo: lista de Class_reglement distinta por Numf
fuente
La inclusión de su clase de comparación (o más específicamente la
AsEnumerable
llamada que necesitaba usar para que funcione) significó que la lógica de clasificación pasó de estar basada en el servidor de la base de datos a estar en el cliente de la base de datos (su aplicación). Esto significa que su cliente ahora necesita recuperar y luego procesar una mayor cantidad de registros, lo que siempre será menos eficiente que realizar la búsqueda en la base de datos donde se pueden usar los índices apropiados.En su lugar, debería intentar desarrollar una cláusula where que satisfaga sus requisitos; consulte Uso de IEqualityComparer con una cláusula LINQ to Entities Except para obtener más detalles.
fuente
Si desea una solución genérica sin boxeo:
uso:
fuente
IEquatable<T>
puede ser una forma mucho más fácil de hacer esto con los marcos modernos.Obtienes una
bool Equals(T other)
función simple y agradable y no hay que perder el tiempo con el casting o la creación de una clase separada.Tenga en cuenta que TIENE que implementarlo
GetHashCode
si usa esto en un diccionario o con algo comoDistinct
.PD. No creo que ningún método Equals personalizado funcione con el marco de la entidad directamente en el lado de la base de datos (creo que lo sabe porque hace AsEnumerable) pero este es un método mucho más simple para hacer Equals simple para el caso general.
Si las cosas no parecen estar funcionando (como errores de clave duplicada al hacer ToDictionary), coloque un punto de interrupción dentro de Equals para asegurarse de que se haya alcanzado y asegúrese de haber
GetHashCode
definido (con la palabra clave override).fuente
.Equals()
método, parece haberse comparadoother.Hometown
consigo mismo, en lugar dethis.Hometown