Tenho alguns sinos em meu banco de dados com o mesmo número. Eu quero obter todos eles sem duplicação. Criei uma classe de comparação para fazer este trabalho, mas a execução da função causa um grande atraso da função sem distinção, de 0,6 seg a 3,2 seg!
Estou fazendo certo ou preciso usar outro 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
fonte
fonte
Respostas:
Sua
GetHashCode
implementação sempre retorna o mesmo valor.Distinct
depende de uma boa função hash para funcionar de forma eficiente, pois cria internamente uma tabela hash .Ao implementar interfaces de classes, é importante ler a documentação para saber qual contrato você deve implementar. 1
Em seu código, a solução é encaminhá
GetHashCode
-Class_reglement.Numf.GetHashCode
lo e implementá-lo apropriadamente lá.Além disso, seu
Equals
método está cheio de códigos desnecessários. Ele poderia ser reescrito da seguinte forma (mesma semântica, ¼ do código, mais legível):Por último, a
ToList
chamada é desnecessária e demorada:AddRange
aceita qualquer,IEnumerable
portanto a conversão para aList
não é necessária. tambémAsEnumerable
é redundante aqui, pois o processamento do resultado causará isso de qualquer maneira.AddRange
1 Escrever código sem saber o que ele realmente faz é chamado de programação de culto à carga . É uma prática surpreendentemente difundida. Basicamente, não funciona.
fonte
GetHashCode
. No entanto, observe que a documentação doIEqualityComparer<T>
não especifica o que fazer com osnull
argumentos - mas os exemplos fornecidos no artigo também não tratamnull
.Experimente este código:
Exemplo de seu uso seria
fonte
GetHashCode
precisa usar a expressão também:return _expr.Invoke(obj).GetHashCode();
Veja esta postagem para um uso dela.Apenas código, com implementação
GetHashCode
eNULL
validação:Exemplo: lista de Class_reglement distinta por Numf
fonte
A inclusão de sua classe de comparação (ou mais especificamente a
AsEnumerable
chamada que você precisava usar para fazê-la funcionar) significava que a lógica de classificação passou de ser baseada no servidor de banco de dados para estar no cliente de banco de dados (seu aplicativo). Isso significa que seu cliente agora precisa recuperar e depois processar um número maior de registros, o que sempre será menos eficiente do que realizar a consulta no banco de dados onde os índices apropriados podem ser usados.Você deve tentar desenvolver uma cláusula where que satisfaça seus requisitos, consulte Usando um IEqualityComparer com uma cláusula LINQ to Entities Except para obter mais detalhes.
fonte
Se você deseja uma solução genérica sem boxe:
uso:
fonte
IEquatable<T>
pode ser uma maneira muito mais fácil de fazer isso com estruturas modernas.Você obtém uma
bool Equals(T other)
função simples e agradável e não há confusão em lançar ou criar uma classe separada.Observe que você TEM que implementar
GetHashCode
se usar isso em um dicionário ou algo semelhanteDistinct
.PS. Não acho que nenhum método Equals personalizado funcione com estrutura de entidade diretamente no lado do banco de dados (acho que você sabe disso porque faz AsEnumerable), mas esse é um método muito mais simples de fazer um Equals simples para o caso geral.
Se as coisas não parecem estar funcionando (como erros de chave duplicados ao fazer ToDictionary), coloque um ponto de interrupção dentro de Equals para ter certeza de que está sendo atingido e certifique-se de ter
GetHashCode
definido (com a palavra-chave override).fonte
.Equals()
método, você parece ter comparadoother.Hometown
a si mesmo, em vez dethis.Hometown