NHibernate e qualche critica alla progettazione

Sebbene apprezzo le potenzialità di NHibernate (e di conseguenza sto rivedendo la mia opinione/scetticismo sugli ORM) NON posso tirarmi indientro dal criticare alcune scelte di progettazione. Ecco una delle mie storie.

NHibernate (e anche hibernate) propone alcuni tipi built-in per aiutare a mappare colonne con comportamenti particolari; "YesNoType" (YesNo) è un esempio di questi tipi con il quale è possibile mappare booleani con colonne CHAR(1) pensate per contenere "Y" o "N". Ma in italia si dice "Si" e "No" e quindi i valori sono "S" e "N"... come fare?

La prima idea è stata quella di estendere il tipo YesNoType e ridefinirne la proprietà "TrueString" che indica il valore stringa da associare a True. Allora è proprio semplice! NO, non è possilbile: TrueString è marcato come "sealed" quindi NON ridefinibile. "TrueString" è esplicitamente marcata con sealed perchè esiste un tipo base che la definisce astratta... bene estenderò anche io il tipo base: "CharBooleanType" nato per "Maps a Boolean Property to a AnsiStringFixedLength column". Semplice anche questo! NO, non è possibile il tipo - marcato come astratto - ha un solo costruttore marcato come internal! :(

Alla fine? Alla fine - come già in altre occasioni simili - mi sono dovuto arrendere e implementare un mio IUserType che riporto qui sotto.

    public class SiNoType : IUserType 
    {
        #region IUserType Members
        public object DeepCopy(object value)
        {
            return value;
        }

        public int GetHashCode(object x)
        {
            return x.GetHashCode();
        }

        public bool IsMutable
        {
            get { return false; }
        }

        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            string name = names[0];
            return !rs[name].Equals("S");
        }

        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            string db_value = (value.Equals(true)) ? "S" : "N";
            IDbDataParameter parameter = (IDbDataParameter)cmd.Parameters[index];
            parameter.Value = db_value;            
        }

        public Type ReturnedType
        {
            get { return typeof(bool); }
        }

        public SqlType[] SqlTypes
        {
            get { return new SqlType[] { new SqlType(DbType.AnsiStringFixedLength, 1) }; }
        }

        bool IUserType.Equals(object x, object y)
        {
            return x.Equals(y);
        }
        #endregion
    }

Non c'era altra soluzione? In realtà credo si sarebbe potuto estendere YesNoType e ridefinirne invece i metodi "NullSafeGet" e "NullSafeSet" cercando di by-passare quindi l'uso di "TrueString"... ma triggerare casi d'uso per iniettare nuovo codice e provare a saltarne altro la ritengo una soluzione poco leggibile e NON sempre efficace perchè si potrebbero trascurare/dimenticare altri casi d'uso della classe che quindi sarebbe zoppa. Ho ritenuto più semplice e LEGGIBILE implementare un tipo custom.

o0O( Sono cattivo se dico che NHibernate si sente che è figlio di un padre nato al sapore di caffè? :-p)

Technorati Tags:

posted @ venerdì 9 marzo 2007 10:57

Print

Comments on this entry:

# re: NHibernate e qualche critica alla progettazione

Left by M.rkino at 09/03/2007 11:52
Gravatar
...è una possibilità che non avevo considerato perchè non conoscevo (eventualnente approfondisco)... ma NON è la ricerca di un'altra soluzione lo scopo del mio post ;-p

# re: NHibernate e qualche critica alla progettazione

Left by Matteo at 09/03/2007 18:13
Gravatar
> Ma in italia si dice "Si" e "No" e quindi i > valori sono "S" e "N"

La tua soluzione è perfetta, ma chi ha deciso di utilizzare l'italiano va appeso al muro.
Comments have been closed on this topic.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011