Entity matching - sei sicuro? l'accendiamo?

Mi vergogno quasi ad ammetterlo, ma effettivamente non ci avevo mai pensato.
Questo fine settimana ho navigato un pò in internet, al fine di trovare qualche idea per arricchire ulteriormente il Domain Model dell'applicazione alla quale sto lavorando e, in particolar modo, definire il più elegantemente possibile un criterio per la comparazione delle entità. La parte che, tendenzialmente, tenevo meno in considerazione era quella relativa all'hashing dell'istanza. Il punto è che, in linea del tutto teorica, il metodo GetHashCode per due tipi differenti può restituire il medesimo valore.
public override Int32 GetHashCode()
{
    IEnumerable<PropertyInfo> signatureProperties = GetSignatureProperties();
    Int32 hashCode = GetType().GetHashCode();

    foreach (PropertyInfo property in signatureProperties)
    {
        Object value = property.GetValue(this, null);

        if (value != null)
            hashCode = hashCode ^ value.GetHashCode();
    }

    return signatureProperties.Any() ? hashCode : base.GetHashCode();
}
Il metodo GetSignatureProperties fornisce la collezione degli elementi a partire dai quali si determina l'hash.
Quest'ultimo, per le considerazioni di cui sopra, deve tenere conto anche del tipo dell'oggetto.
Insomma, io credo che la questione sia tutt'altro che banale, e questo post rappresenta a mio avviso un'autentica miniera di best-pratices.
Giusto a titolo di esempio, qualcuno si è mai posto il problema di valutare l'equivalenza tra una entity POCO e il suo proxy?

posted @ lunedì 4 ottobre 2010 9.44

Print

Comments on this entry:

# re: Entity matching - sei sicuro? l'accendiamo?

Left by raffaeu at 05/10/2010 4.38
Gravatar
Beh ma la mia entity POCO, qualsiasi O/RM tu usi, avra' sempre un bel
object PrimaryKey ...
Va bene la persistence ignorance ma comunque in qualche modo dovrai mappare POCO con Proxy, no?

# re: Entity matching - sei sicuro? l'accendiamo?

Left by naighes at 05/10/2010 8.28
Gravatar
Facciamo una casistica.

public class Foo
{
public virtual String ID { get; set; }
public virtual String Name { get; set; }
}

public class Bar
{
public virtual String ID { get; set; }
public virtual String Name { get; set; }
}

Nel caso in cui un'istanza di Bar e un'istanza di Foo abbiano i medesimi valori per entrambe le proprietà, il metodo GetHashCode restituisce lo stesso valore, che non è accettabile. Questa è l'idea alla base del "hashing come funzione del tipo".
Utilizzare questo approccio, però, non sconggiura un ulteriore problema.

public class BarProxy
{
public override String ID { get; set; }
public override String Name { get; set; }
}

Prendiamo quindi, in questo caso, un'istanza di Bar e un'istanza di BarProxy. Se hanno lo stesso valore per entrambe le proprietà, il metodo GetHashCode restituisce comunque un valore diverso, per le considerazioni di cui sopra.
Ecco perchè, nel link che ho postato, si fa esporre alla Entity un metodo GetTypeUnproxied(), che sarà utilizzato per il calcolo dell'hash.

Ti torna raffaeu, oppure rientra nel mio inesauribile registro di vaneggiamenti?! :-)

# re: Entity matching - sei sicuro? l'accendiamo?

Left by Aldo at 13/10/2010 9.34
Gravatar
La classe base e il suo proxy rappresentano la stessa entità quindi a mio avviso è corretto che restituiscano lo steso hash, io di solito nell'implementazione di equals della classe base testo il tipo e confronto la chiave naturale partendo dal presupposto che, per definizione, l'hash di una entity E' l'hash della sua chiave. Ciao.

# re: Entity matching - sei sicuro? l'accendiamo?

Left by naighes at 13/10/2010 9.48
Gravatar
> La classe base e il suo proxy rappresentano
> la stessa entità quindi a mio avviso è
> corretto che restituiscano lo steso hash
Appunto, è quello che sto dicendo io, ed è una delle ragioni che motivano l'implementazione alla quale faccio riferimento.

> io di solito nell'implementazione di
> equals della classe base testo il tipo
> e confronto la chiave naturale partendo
> dal presupposto che, per definizione,
> l'hash di una entity E' l'hash della sua chiave.
Dunque, sull'implementazione di "Equals", possiamo essere -sostanzialmente- daccordo.
Sull'hashing, invece, no, perchè puoi avere, ipoteticamente, una classe "Product" e una classe "Category" che dispongono dello stesso valore per la Primary Key.
Ti torna quanto sto dicendo?

# re: Entity matching - sei sicuro? l'accendiamo?

Left by Aldo at 13/10/2010 18.15
Gravatar
Si e no.. Perchè due entità di tipo diverso e che non sono uno il proxy dell'altro sono automaticamente diverse a prescidere dall'hash, quindi un implementazione base (tralascio qualche caso.. tipo l'identità) di equals potrebbe essere:

public override bool Equals(object obj)
{
if (obj != null
&& obj is MioTipo)
{
MioTipo other = (MioTipo) obj;
return this.Key.Equals(other.Key);
}

return false;
}

Ti torna?

# re: Entity matching - sei sicuro? l'accendiamo?

Left by naighes at 13/10/2010 23.25
Gravatar
Aldo, non credo sia opportuno "trascurare" l'hashing.
Il punto fondamentale, come ho più volte ribadito, è che due tipi diversi che, ipoteticamente, hanno lo stesso valore per la Primary Key non possono generare lo stesso hash.
Nell'ipotetico caso nel quale tu debba operare con delle tabelle hash, si originerebbero comportamenti disattesi, non trovi?

Your comment:



 (will not be displayed)


 
 
 
Please add 6 and 6 and type the answer here:
 

Live Comment Preview:

 
«settembre»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011