2010-09-14 6 views
3

Je suis en train d'écrire un cadre pour une réécriture d'une application existante. Nous disposons d'un modèle de données d'environ 900 tableaux avec 11 000 champs au total et de bases de données d'environ 120 Go sur le terrain. Les éléments de base de ma nouvelle implémentation sont WPF, NHibernate 3, C#, .NET 4.0, NHibernate.Validator et Spring. L'application elle-même est très riche en données/transactions et notre plus grande installation compte environ 300 utilisateurs simultanés.Partir de zéro avec NHibernate: conseils pour une nouvelle application de grande taille

Quelques choses que je voudrais commentaires sur sont:

  • Spring un bon choix? Pourquoi devrais-je en choisir un autre (Castle?). J'ai des problèmes avec le temps de démarrage, mais j'ai été capable de ramener cela à 14 secondes. Cependant, je n'ai pas remarqué beaucoup de différence entre Spring et Castle. Des temps de démarrage plus courts sont bien sûr les bienvenus; J'utilise des champs d'identité, mais je comprends que ce n'est pas la meilleure option. Quelle alternative viable existe-t-il?

  • L'affichage des données se fait avec des sessions courtes, une par requête. D'autre part, la saisie de données a une session/transaction pour toute la durée d'un flux de travail, ce qui peut prendre jusqu'à 10-20 minutes maximum (2-4 minutes est plus habituel). Existe-t-il des alternatives à une session/transaction pour toute cette durée et comment pourrais-je l'installer?

Je suis ouvert à tous et toutes les entrées et souhaitent intégrer les idées des personnes qui ont travaillé plus longtemps, et ont plus d'expérience avec NHibernate que moi.

(BTW: Je sais que je suis en chemin sur ma tête, mais c'est la façon dont je le préfère.)

EDIT: j'étais trop sévère en ce qui concerne HiLo, mais après quelques recherches Guid de ne semblent adapter ma situation mieux.

+1

HiLo * est une bonne idée. – Jay

+0

J'ai lu plus à ce sujet et recherché par exemple. l'implémentation dans NHibernate, et je dois dire que ça a l'air intéressant. Je pense que j'ai mal interprété la documentation antérieure. Je vais considérer cela. –

+0

J'ai décidé d'aller avec Guid. Ce choix est dû au fait que je dois prendre en charge la réplication, j'aime l'idée d'avoir des ID uniques sur toutes les entités et cela me laisserait trop peu de valeurs pour y mettre tous les ID. Le système hérité ne possédait pas d'ID de substitution pour toutes les entités, ce qui cause des problèmes pour ce nouveau système. –

Répondre

1

Hilo est l'approche la plus rapide pour attribuer des identifiants. L'utilisation de champs d'identité fonctionne et est plus sûre (voir ci-dessous), mais puisque l'identificateur est généré par la base de données, chaque insertion d'une ligne nécessite une opération de lecture pour déterminer l'identificateur de la ligne.

Si vous utilisez hilo, assurez-vous de bien comprendre le fonctionnement de l'algorithme. (Je pense qu'il est décrit ailleurs sur ce site.) Si vous faites de mauvais choix pour le type de données de la colonne ou de hilo, ou la valeur "lo", vous pouvez vous retrouver avec wraparound, ce qui entraînerait la génération de nombres déjà utilisés. ce qui est bien sûr très mauvais.

La manière habituelle de gérer la saisie de données consiste à fermer la session, à effectuer l'entrée de données, puis à joindre les objets mis à jour à une nouvelle session. Ceci est couvert dans la documentation. La chose délicate à attacher est la suivante: disons que l'objet A contient une référence à l'objet B, et l'objet B contient une référence à l'objet C. Si vous avez "touché" les objets A et B pendant la session initiale, A et B aura été chargé, et B contiendra une référence de proxy à C. Si vous attachez A à la nouvelle session, mais oubliez de joindre B, la référence de proxy de B pointera toujours sur l'ancienne session fermée, ce qui entraînera une exception si vous essayez de le suivre.

Il peut être plus difficile que cela ne semble l'être. Au cours de la session initiale, si vous avez appelé une fonction qui a fait une sorte de recherche dans votre graphe d'objets, il peut être difficile de savoir plus tard exactement quels objets doivent être attachés à la nouvelle session pour que tout fonctionne correctement.En fonction de la fiabilité de votre connexion à votre base de données, il peut être préférable de garder la session ouverte pour l'opération de saisie de données et d'éviter les problèmes potentiels liés à l'association des objets à une nouvelle session. Cela dépend beaucoup de la complexité de votre modèle d'objet et de ce que vous devez faire avec les objets.

La base de données que vous utilisez a également une importance. Par exemple, PostgreSQL utilise MVCC, donc une session ouverte ne bloque jamais les autres utilisateurs à partir de la base de données. Dans une base de données qui utilise le verrouillage de ligne, les verrous constituent une grande partie du problème avec des sessions longues.

+0

J'ai lu plus sur HiLo, et Guids semble être une meilleure option. A les mêmes avantages cependant. En ce qui concerne les sessions: l'intégrité des données est très importante pour nous, donc je m'inquiète surtout de savoir s'il faut garder une transaction ouverte pour l'ensemble de la transaction commerciale. Il est difficile de déterminer l'impact de l'une ou l'autre option sur le long terme. –

+0

Le principal problème avec une transaction longue est que vous vous retrouvez avec des lignes bloquées dans la base de données pendant une longue période de temps. Cela peut forcer les autres opérations de base de données à attendre que vous ayez terminé (cela dépend du niveau d'isolation) et si la base de données détecte un blocage, elle choisira arbitrairement une transaction à restaurer pour rompre le blocage. –

+0

Une autre chose qui mérite d'être mentionnée est que si une tentative d'écriture d'objets dans la base de données échoue et que vous voulez réessayer, vous êtes supposé recommencer avec de nouveaux objets. (Les objets peuvent être mis à jour en raison de la tentative d'écriture échouée.) Si les objets n'ont jamais été dans la base de données, le plus simple est de définir un constructeur de copie qui copie tout sauf l'identifiant, et clone tous des objets. Votre constructeur de copie ne clone pas la couche proxy de l'objet, qui est la partie qui est "foiré". –

Questions connexes