LINQ Exceto usando personalizado Comparador
-
06-07-2019 - |
Pergunta
Eu estou tentando usar o "exceto" método em um conjunto de resultados LINQ usando uma implementação personalizada se IEqualityComparer para excluir certos resultados com base no valor de um único campo do conjunto de resultados.
Assim, de forma simplificada eu tenho ...
'' Get collection of published sites...
Dim List1 = (From i In db.Sites _
Where (i.StatusID = published) _
Select i.SiteID, _
i.SiteName)
'' Find those with a pending site, but exclue all those whose SiteID is in List1...
Dim insComparer = New insCompare
Dim List2 = (From i In db.Sites _
Where (i.StatusID = pending) _
Select i.SiteID, _
i.SiteName).Except(List1, insComparer)
Meu Comparer é o seguinte ...
Public Class insCompare
Implements System.Collections.Generic.IEqualityComparer(Of Object)
Public Function Equals1(ByVal x As Object, ByVal y As Object) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Object).Equals
Return IIf(x.SiteID = y.SiteID, True, False)
End Function
Public Function GetHashCode1(ByVal x As Object) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Object).GetHashCode
Return x.SiteID.ToString.ToLower.GetHashCode()
End Function
End Class
Eu recebo uma exceção de elenco inválido na linha ".Except" com a mensagem "Não é possível objeto fundido do tipo '... insCompare' para digitar 'System.Collections.Generic.IEqualityComparer'"
Alguém pode lançar luz sobre por que isso pode ser por favor.
Solução
O problema aqui é que você implementar IEqualityComparer (Of Object), mas as suas listas são List (Of AT), onde AT é um tipo anônimo, para que você não pode implementar IEqualityComparer (Of AT).
Eu acho que suas escolhas são:
- Declarar uma classe / struct para segurar o SideID / SiteName, e selecione em uma instância dessa classe, em seguida, implementar IEqualityComparer (Of NewClass).
- Use as chamadas de ligação tardia (ie. opção off explícita, como parece que você está fazendo agora), e colocar um .Cast (Of Object) () chamada em ambas as listas antes de chamar Exceto.
Outras dicas
Use o código a seguir.
from t in db.Sites
where
!
(from t0 in db.Sites2
select new {
t0.SomeID
}).Contains(new { t.SomeID })
select t
este é baseado em não em condição. Eu acho que isso vai te ajudar. U estão fazendo alguma coisa complexa.
Parece que ele está pedindo que seu comparer implementar o IEqualityComparer
interface de não-genérico, enquanto teus implementos IEqualityComparer (Of Object)
, que é uma interface diferente.
Parece que você está usando um banco de dados como o back-end. Você não pode fornecer um comparador personalizado para isso, como ele não pode ser mapeado para TSQL.
Você já tentou Contains
? ou seja where !List1.Contains(i.SiteID)
?