2010-06-05 3 views
1

Actuellement, nous utilisons NHibernate pour mapper des objets métier aux tables de base de données. Ces objets métier appliquent les règles métier: Les accesseurs set jetteront une exception sur place si le contrat pour cette propriété est violé. De plus, les propriétés imposent des relations avec d'autres objets (parfois bidirectionnels!). Eh bien, chaque fois que NHibernate charge un objet de la base de données (par exemple lorsque ISession.Get (id) est appelée), les accesseurs définis des propriétés mappées sont utilisés pour placer les données dans l'objet.Avec quelles classes dois-je mapper avec NHibernate?

Ce qui est bien, c'est que le niveau intermédiaire de l'application applique la logique métier. Ce qui est mauvais c'est que la base de données ne le fait pas. Parfois, la merde trouve son chemin dans la base de données. Si la merde est chargée dans l'application, elle est bloquée (lève une exception). Parfois, il devrait clairement être libéré sous caution parce qu'il ne peut rien faire, mais que faire s'il peut continuer à fonctionner? Par exemple, un outil d'administration qui rassemble des rapports en temps réel risque fortement d'échouer inutilement au lieu de permettre à un administrateur de résoudre un problème (potentiel).

Je n'ai pas d'exemple sur moi en ce moment, mais dans certains cas, laisser NHibernate utiliser les propriétés de «porte d'entrée» qui imposent également des relations (en particulier bidi) conduit à des bogues.

Quelles sont les meilleures solutions?

Actuellement, je, sur une propriété par propriété base, créer une « porte arrière » juste pour NHibernate:

public virtual int Blah {get {return _Blah;} set {/*enforces BR's*/}} 
protected virtual int _Blah {get {return blah;} set {blah = value;}} 
private int blah; 

J'ai montré ci-dessus en C# 2 (pas de propriétés par défaut) pour montrer comment cela se nous fondamentalement 3 couches de, ou vues, à bla !!! Bien que cela fonctionne certainement, cela ne semble pas idéal car cela nécessite que le BL fournisse une interface (publique) pour l'application en général, et une autre interface (protégée) pour la couche d'accès aux données. Il y a un problème supplémentaire: À ma connaissance, NHibernate ne vous permet pas de faire la distinction entre le nom de la propriété dans le BL et le nom de la propriété dans le modèle d'entité (c'est-à-dire le nom que vous utilisez lorsque vous requête, par exemple via HQL - chaque fois que vous donnez à NHibernate le nom (chaîne) d'une propriété). Cela devient un problème quand, au début, les BR pour certaines propriétés Blah ne posent aucun problème, donc vous vous référez à cela dans votre mapping O/R ... mais plus tard, vous devez ajouter quelques BR qui deviennent un problème, donc Ensuite, vous devez modifier votre mappage O/R pour utiliser une nouvelle propriété _Blah, qui casse toutes les requêtes existantes en utilisant "Blah" (problème courant de programmation par chaînes).

Est-ce que quelqu'un a résolu ces problèmes ?!

+2

On ne sait pas pourquoi vous ne pouvez pas empêcher des données non valides d'entrer dans votre base de données. Je ne pense pas qu'il existe une solution de contournement général pour ce scénario (indépendamment du fait que NHibernate soit impliqué ou non). Vous pouvez peut-être constamment interroger la base de données à la recherche de données non valides, puis tenter de la corriger avant que NHibernate ne tente de la charger. –

+0

Juste trouvé une discussion connexe: http://stackoverflow.com/questions/129773/nhibernate-map-to-fields-or-properties – apollodude217

+0

@Michael: Bonne question/commentaire.Généralement, il s'agit d'une application héritée où les données préexistantes ne répondent pas aux exigences de l'entreprise (je sais que nous devrions les nettoyer) ou lorsqu'une autre application héritée permet aux mauvaises données d'entrer. – apollodude217

Répondre

3

Même si j'ai trouvé que la plupart de vos problèmes d'architecture étaient problématiques, NHibernate utilise habituellement le backing field au lieu du setter.

Dans votre exemple ci-dessus, vous n'avez pas besoin de définir une propriété protégée supplémentaire. Il suffit de l'utiliser dans la mise en correspondance:

<property name="Blah" access="nosetter.lowercase"/> 

Ceci est décrit dans la documentation, http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-property (. Tableau 5.1 Stratégies d'accès)

+1

Il s'agit en fait de la stratégie d'accès préférée d'Hibernate. ne pas être appliqué lors de la lecture de la base de données, vous devriez juste avoir ce qu'il y a dedans. Pour une raison quelconque, les gars de NHibernate ne sont pas d'accord et préconisent/recommandent la stratégie d'accès à la propriété. –

+1

@Fried c'est probablement parce que le setter n'est pas habituellement où les règles sont appliquées avec .NET/NHibernate. En fait, la plupart des entités persistantes utilisent des propriétés automatiques, de sorte que les corps getter/setter sont générés. –

+0

Merci pour vos commentaires! @Diego, Il me semble que cette solution réduirait les vues à Blah dans le code C# 2 (juste la propriété et le champ). Mais en C# 3, il me faudrait 2 couches pour commencer (propriété et champ) - c'est-à-dire que Blah ne peut pas être une propriété par défaut; il doit être codé à la main s'il existe une logique métier à implémenter ou non. Est-ce que je comprends bien? – apollodude217

Questions connexes