Ci troviamo spesso nella situazione di dover effettuare dei distinct di oggetti di una collection di cui ci interessa che il distinct effettuato riguardi un sottogruppo di campi. Capita anche, lavorando con iQuerable provenienti da un orm interfacciato con un database quali EntityFramework o Linq-To-Sql classes, che le entità in oggetto in realtà comprendano dei campi scritti da trigger database che non ci interessano particolarmente. Oltre all'iterazione dell'intera collection o dell'intero iQuerable (che tra l'altro causa la materializzazione in ram di ogni singola entità iterata con conseguente aumento del costo computazionale) una soluzione relativamente standard consiste nel creare un'implementazione di IEqualityComparer per la classe specifica delle entità in considerazione.
Prendo ad esempio una classe generica, dotata di alcuni attributi significativi ed altri superflui
Public Class Albero Dim Altezza As Integer Dim Posizione As String Dim Peso As Integer Dim Specie As Integer Dim ColoreFoglie as Color Dim DataRilevazione as Date Dim OperatoreRilevazione as String End Class
e scrivo un'overload di Equals e GetHashCode secondo le proprietà che mi interessano
Public Class AlberoCompare Implements System.Collections.Generic.IEqualityComparer(Of Albero) Public Function Equals(ByVal x As Albero, ByVal y As Albero) As Boolean Return x.Altezza=y.Altezza and x.Peso=y.Peso and x.Specie=y.Specie End Function Public Function GetHashCode(ByVal x As Albero) As Integer Return x.Altezza + x.Peso End Function End Class
Basterà passare questa classe di comparazione come parametro al metodo distinct per ottenere il risultato desiderato
Un'alternativa più veloce invece consiste nel raggruppare le entities secondo i parametri di interesse
e quindi selezionare il primo elemento di ogni gruppo:Dim group = (From p As Albero In db.Alberi Group p By p.Altezza, p.Peso, p.Specie Into Group Select Group)
dim result = group.Select(Function(d) d.First())
ottenendo nuovamente una collection o un iQuerable dello stesso tipo di entities (nel caso di estrazione dati da un orm, questa soluzione non materializza nulla in ram fino alla risoluzione dell'IQuerable)
Nessun commento:
Posta un commento