Belius' Blog

Il blog di Simone Belia
posts - 16, comments - 49, trackbacks - 23

Recuperare solo i valori essenziali con Nhibernate

L'infrastruttura di NHibernate ci permette di recuperare con pochi sforzi le informazioni che stanno nel DB sottoforma di nostre classi opportunamente istruite.

Bene....e che c'è di nuovo?
Nulla....ma ipotizziamo questo:

Ho una classe Customer che contiene 40 proprietà (non associazioni) che la descrivono.
Ora voglio che in un menu a tendina della mia applicazione vengano inseriti tutti i Customer così da farne scegliere uno all'utente.

In questo scenario quello che mi serve è solo l'ID del customer ed il suo nome....allora perchè caricarsi tutti quanti i suoi dati?

Negli ultimi progetti che ho sviluppato con NHibernate ho cercato di trovare una metodologia per venire incontro a questa comune problematica in maniera "comoda" e "tipizzata"....e spero che quello che ho fatto possa rilevarsi utile anche per voi!!! :-)

Per prima cosa mi sono costruito una classe generica che mi permetta di descrivere i miei valori: 

public class NameValueDTO<Tv, Tn>
{
   private Tn _name;
   private Tv _value; 

   public Tn Name 
   { 
      get { return _name; } 
   } 
        
   public Tv Value 
   { 
      get { return _value; } 
   }

   public NameValueDTO(Tv value, Tn name)
   {
      _name = name;
      _value = value;
   }
}

Successivamente mi sono costruito un metodo generico rappresentante la classe per la quale voglio estrapolare i valori (nel nostro caso Customer) ed al quale passerò il nome della proprietà dell'oggetto che vorrò visualizzare.

public IList<NameValueDTO<int,string>> GetNameValue<T>(string propName)
{
   ICriteria criteria = _session.CreateCriteria(typeof(T));
   ProjectionList pl = Projections.ProjectionList();
                        
   pl.Add(Projections.Id());
   pl.Add(Projections.Property(propName));
   criteria.SetProjection(pl);
                        
   criteria.SetResultTransformer(new NHibernate.Transform.AliasToBeanConstructorResultTransformer(
               typeof(NameValueDTO<int,string>).GetConstructors()[0]));

   return criteria.List<NameValueDTO<int, string>>();
}
 

Esaminiamo il codice.
La prima istruzione crea un oggeto Criteria basandosi sul tipo della classe che ho passatto come parametro del generic.
Successviamente creo una ProjectionList che mi servirà per incapsulare i campi che desidero "aggregare" (anche se non è la parola giusta in questo esempio....:-)).

L'istruzione successiva è la più interessante.
SetResultTransformer dice ad NH di trasformare (AliasToBeanConstructorResultTransformer) i valori di ritorno dalla query istanziare nel tipo di oggetto che gli ho specificato (typeof(NameValueDTO<int,string>)) utilizzando il primo costruttore GetConstructors()[0];

A questo punto il gioco è fatto....richiamando il metodo GetNameValue mi verrà ritornata la mia bella collezione con solo i campi richiesti.

 

Print | posted on venerdì 16 novembre 2007 18.57 | Filed Under [ NHibernate ]

Feedback

Gravatar

# re: Recuperare solo i valori essenziali con Nhibernate

solo due dubbi:
1) non dovresti associare le projections al criterio? qualcosa tipo
criteria.SetProjection(pl);

2) non mi funziona perché mi dice: could not instantiate: nHibConsoleTest.NameValueDTO`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
perché (innerException)
{"Object of type 'System.Int32' cannot be converted to type 'System.String'."} mmmh...

io ho la classe
public class Agente
{
private int idAgente;

public virtual int IdAgente
{
get
{
return idAgente;
}
set
{
idAgente = value;
}
}


private string nome;

public virtual string Nome
{
get
{
return nome;
}
set
{
nome = value;
}
}
}

ho sbgliatoquaccheccosaaa? :)
17/11/2007 12.35 | marco
Gravatar

# re: Recuperare solo i valori essenziali con Nhibernate

Ciao Marco......sotto i punti:

1. Bhè si....ma quando scrivi il codice veloce per l'articolo una riga in meno si può perdonare...no?


2. NHibernate usa la reflection per esaminare il costruttore e quindi si aspetta che il costruttore abbia i parametri nello stesso ordine di come li associ nella ProjectionList.....ovvero se hai


pl.Add(Projections.Id());
pl.Add(Projections.Property("NomeAgente"));

il costruttore della tua classe dovrebbe essere

public Agent(int id, string nome)


se già avevi fatto così fammi avere il tuo codice che gli do un occhio.


17/11/2007 20.12 | Belius
Gravatar

# re: Recuperare solo i valori essenziali con Nhibernate

1)eheh nonmi sono spiegato... sono talmente ignorante che non ne ero certo...

2)rospo che non sono altro: avevo copiato male la classe
public class NameValueDTO<Tv, Tn>, invertendo Tv e Tn: public class NameValueDTO<Tn, Tv>, così che poi il costruttore risultava "arbirato"...:)
comunque è buonissimo, anche perché ho verificato (uomo di poca fede) e in effetti la query fatta è:
SELECT this_.IdAg as y0_, this_.Nome as y1_ FROM Ag this_
nothing more, nothing less :)
19/11/2007 9.46 | marco

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 3 and 7 and type the answer here:

Powered by: