NHibernate aggiunge una colonna non mappata nell'interceptor
-
05-07-2019 - |
Domanda
Sto cercando di salvare un'entità mappata usando NHibernate ma il mio inserimento nel database non riesce perché la tabella sottostante ha una colonna che non consente valori null e NON è mappata nel mio oggetto dominio. Il motivo per cui non è mappato è perché la colonna in questione supporta un'applicazione legacy e non ha rilevanza per la mia applicazione, quindi mi piacerebbe non inquinare la mia entità con la proprietà legacy.
So che potrei usare un campo privato all'interno della mia classe - ma questo mi sembra ancora brutto. Ho letto che posso usare un intercettore NHibernate e sovrascrivere il metodo OnSave () per aggiungere nella nuova colonna proprio prima che la mia entità venga salvata Ciò si sta rivelando difficile poiché non riesco a capire come aggiungere un'istanza di Nhibernate.type.IType al parametro types di OnSave del mio interceptor.
La mia Entità assomiglia approssimativamente a questo:
public class Client
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
public virtual string Name { get; set; }
public virtual string Phone { get; set; }
public virtual string Email { get; set; }
public virtual string Url { get; set; }
}
E il mio intercettore
public class ClientInterceptor : EmptyInterceptor
{
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
{
if (entity is Client)
{
/*
manually add the COM_HOLD column to the Client entity
*/
List<string> pn_list = propertyNames.ToList();
pn_list.Add("COM_HOLD");
propertyNames = pn_list.ToArray();
List<Object> _state = state.ToList();
_state.Add(false);
state = _state.ToArray();
//somehow add an IType to types param ??
}
return base.OnSave(entity, id, state, propertyNames, types);
}
}
Qualcuno ha qualche idea su come farlo correttamente?
Soluzione
Non posso dirlo con certezza dal momento che non l'ho mai fatto (come Stefan, preferisco anche solo aggiungere una proprietà privata), ma puoi semplicemente aggiungere un NHibernate.Type.BooleanType
all'array types
?
List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();
Modifica
Sì, sembra che tu abbia ragione; i tipi hanno un costruttore internal
. Ho scavato e ho trovato TypeFactory
:
Le applicazioni dovrebbero usare statica metodi e costanti su NHibernate.NHibernateUtil se il IType predefinito è abbastanza buono. Ad esempio, TypeFactory dovrebbe solo essere usato quando la stringa deve avere una lunghezza di 300 anziché 255. A questo punto NHibernate.String non ti fornisce l'IType corretto. Utilizzare invece TypeFactory.GetString (300) e mantenere a variabile locale che contiene un riferimento a IType.
Quindi sembra che ciò che vuoi sia NHibernateUtil
:
Fornisce l'accesso all'intera gamma di NHibernate tipi integrati. Io digito le istanze possono essere utilizzate per associare i valori per interrogare i parametri. Anche una fabbrica per nuovi BLOB e BLOB.
typeList.Add(NHibernateUtil.Boolean);
Altri suggerimenti
Personalmente non lo farei così complicato. Aggiungerei la proprietà privata e gli assegnerei un valore predefinito - finito. Potresti anche considerare un valore predefinito nel database, quindi non devi fare nient'altro.
private virtual bool COM_HOLD
{
get { return false; }
set { /* make NH happy */ }
}
Prima di scrivere un intercettore per quello che prenderei in considerazione di scrivere un trigger di database. Perché con l'Interceptor stai "inquinando" il tuo livello di accesso ai dati. potrebbe renderlo instabile e tu potresti avere strani problemi.