Ieri ho fatto una pagina asp.net banalissima, che mostra la lista di messaggi ricevuti da un utente. Utilizzo nhibernate, mi faccio un oggetto che espone una serie di metodi per essere utilizzato con l'objectDataSource, faccio la pagina e tutto ok. Poi aggiungo l'attributo "Read" per far vedere all'utente quali messaggi sono stati letti, intercetto l'evento di selezione della row, chiamo un metodo che recupera l'istanza dal db ed aggiorna la proprietà Read, poi chiamo il DataBind della gridview per mostrare i risultati aggiornati.
A questo punto si presenta un errore strano, se seleziono il primo messaggio si presenta un errore, per tutti gli altri messaggi no, L'errore è "Object does not match target type. ". Dopo 10 min di smattimento capisco la ragione. Il fatto è che utilizzando session.load con nhibernate vi viene restituito un proxy dell'oggetto MEssage. LA situazione è questa, io seleziono il messaggio X, lo carico con session.load, aggiorno la proprietà read e quando dopo faccio una criteria query, l'oggetto è già in sessione e non viene ricostruito. A questo aggiungiamo che l'objectDataSource esamina con reflection il primo oggetto della lista per trovare i suoi tipi e da quì si capisce il problema. Supponiamo di avere 3 messaggi e di selezionare il secondo, quando chiedo la lista dei messaggi nhibernate restituisce
Message, Proxy, Message
Perchè il messaaggio 2 era già stato preso con load per essere aggirnato. Tramite reflection vengono presi i property info del primo oggetto, di tipo Message e non ci sono problemi ad accedere a Proxy che eredita da MEssage. MA se selziono il primo ho
Proxy, Message, Message
a questo punto tramite reflection vengono prese le propertyinfo di Proxy e quando si tenta di accedere ad un oggetto Message che è più su nella gerarchia di Proxy si genera errore. Subito parto in quarta e cerco di risolvere il tutto con una ITypedList, perchè ricordo di avere avuto problemi analoghi anni fa con un progetto winforms ma non funziona, cerco in rete e trovo anche questo post di Marco sull'argomento, lo leggo e ho conferma di avere fatto tutto bene. Il problema è che l'objectDataSource lavora sempre con reflection sul primo elemento per cui nisba, la ITypedList non va. Leggendo in rete ho trovato questo articolo di Manuel Abadia fatto veramente bene da cui ci sono anche un sacco di link per capire a fondo come lavorano gli object data source.
Purtroppo il tempo è tiranno e visto che non posso spendere troppo tempo per fare la soluzione elegante, sono dovuto purtroppo ricorrere alla soluzione Quick And Dirty. In pratica dal mio oggetto che utilizzo come sorgente per l'objectDataSource prima di restituire i dati controlo il primo elemento della lista e se non è un Message lo sostituisco con un istanza nuova di Message passando per il copyConstructor, non mi piace molto ma funziona. A mia discolpa accuso l'ObjectDataSource perchè non permette di specificare direttamente da codice il tipo di dato che viene restituito (O forse non lo ho trovato io ?? )
Alk.