LINQ Excepto el uso de Comparer personalizado
-
06-07-2019 - |
Pregunta
Estoy intentando utilizar el " Excepto " método en un conjunto de resultados LINQ utilizando una implementación personalizada si IEqualityComparer excluye ciertos resultados basados ??en el valor de un solo campo del conjunto de resultados.
Entonces, en forma simplificada tengo ...
'' 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)
Mi comparador es el siguiente ...
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
Recibo una excepción de conversión no válida en el " .Excepto " línea con el mensaje " No se puede emitir un objeto de tipo '... insCompare' para escribir 'System.Collections.Generic.IEqualityComparer' "
¿Alguien puede arrojar luz sobre por qué esto podría ser por favor?
Solución
Su problema aquí es que implementa IEqualityComparer (Of Object), pero sus listas son List (Of AT) donde AT es un tipo anónimo, por lo que no puede implementar IEqualityComparer (Of AT).
Creo que sus opciones son:
- Declare una clase / estructura para contener el SideID / SiteName, y seleccione en una instancia de esa clase, luego implemente IEqualityComparer (Of NewClass).
- Use llamadas con retraso (es decir, opción explícita desactivada, como parece que está haciendo ahora), y coloque una llamada .Cast (Of Object) () en ambas listas antes de llamar Excepto.
Otros consejos
Use el siguiente código.
from t in db.Sites
where
!
(from t0 in db.Sites2
select new {
t0.SomeID
}).Contains(new { t.SomeID })
select t
esto se basa en no en condiciones. Creo que esto te ayudará. Estás haciendo algo complejo.
Parece que le pide a su comparador que implemente la interfaz no genérica IEqualityComparer
, mientras que la suya implementa IEqualityComparer (Of Object)
, que es una interfaz diferente.
Parece que está utilizando una base de datos como back-end. no puede proporcionar un comparador personalizado para esto, ya que no se puede asignar a TSQL.
¿Has probado Contiene
? es decir, where! List1.Contains (i.SiteID)
?