NHibernate ajoute une colonne non mappée dans un intercepteur
-
05-07-2019 - |
Question
J'essaie de sauvegarder une entité mappée à l'aide de NHibernate, mais mon insertion dans la base de données échoue car la table sous-jacente contient une colonne qui n'autorise pas les valeurs NULL et N'EST PAS mappée dans mon objet de domaine. La raison pour laquelle il n'est pas mappé, c'est parce que la colonne en question prend en charge une application héritée et n'a aucune pertinence pour mon application. Je souhaite donc ne pas polluer mon entité avec la propriété héritée.
Je sais que je pourrais utiliser un champ privé à l'intérieur de ma classe - mais cela me semble toujours désagréable. J'ai lu le fait que je peux utiliser un intercepteur NHibernate et remplacer la méthode OnSave () pour l'ajouter. dans la nouvelle colonne juste avant que mon entité soit sauvegardée. Cela s’avère difficile, car je ne sais pas comment ajouter une instance de Nhibernate.type.IType au paramètre types de la fonction OnSave de mon intercept.
Mon entité ressemble à peu près à ceci:
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; }
}
Et mon intercepteur
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);
}
}
Quelqu'un a-t-il des idées sur la manière de procéder correctement?
La solution
Je ne peux pas dire avec certitude puisque je n’ai jamais fait cela (comme Stefan, je préfère également ajouter une propriété privée), mais pouvez-vous simplement ajouter un NHibernate.Type.BooleanType
vers le tableau types
?
List<IType> typeList = types.ToList();
typeList.Add(new BooleanType());
types = typesList.ToArray();
MODIFIER
Oui, on dirait que vous avez raison. les types ont un constructeur internal
. J'ai creusé et j'ai trouvé TypeFactory
:
Les applications doivent utiliser statique méthodes et constantes sur NHibernate.NHibernateUtil si le IType par défaut est assez bon. Par exemple, le TypeFactory devrait seulement être utilisé lorsque la chaîne doit avoir une longueur de 300 au lieu de 255. À ce stade NHibernate.String ne vous fournit pas le type informatique correct. Utilisez plutôt TypeFactory.GetString (300) et gardez un variable locale contenant une référence à IType.
On dirait donc que ce que vous voulez, c'est NHibernateUtil
:
Permet d'accéder à la gamme complète de NHibernate types intégrés. J'écris les instances peuvent être utilisées pour lier des valeurs pour interroger des paramètres. Aussi une usine pour les nouveaux blobs et clobs.
typeList.Add(NHibernateUtil.Boolean);
Autres conseils
Personnellement, je ne le ferais pas si compliqué. Je voudrais ajouter la propriété privée et lui attribuer une valeur par défaut - fini. Vous pouvez également considérer une valeur par défaut dans la base de données, vous n'avez rien d'autre à faire.
private virtual bool COM_HOLD
{
get { return false; }
set { /* make NH happy */ }
}
Avant d’écrire un intercepteur, j’envisagerais d’écrire un déclencheur de base de données. Parce qu'avec l'Interceptor, vous êtes "polluant" votre couche d'accès aux données. Cela pourrait le rendre instable et vous pourriez avoir d'étranges problèmes.