Question

J'ai lu à plus d'un endroit qu'en utilisant l'identifiant de NHibernate comme La clé primaire est considérée comme une mauvaise pratique car les identifiants sont générés côté serveur. Nous avons donc besoin d'une réponse du serveur concernant les identifiants générés. (Je pense que j’ai aussi vu un article d’Ayende disant que le serveur ms-sql peut avoir des problèmes générer l'identifiant, ce qui peut entraîner des violations de clé primaire)

Maintenant, disons que j'ai un modèle de domaine très simple: les blogs et la publication. où chaque blog peut avoir de nombreux articles et chaque article appartient à un seul blog EXACTEMENT (relation un à plusieurs) mais NOUS SAUVONS SEULEMENT LA POSTE - > Relation de blog et non le blog - > Messages

Supposons maintenant que j'utilise NHibernate WITH Idenitifer Id Generation tel que je n'utilise pas de cascade, de sorte que j'ai dans mon code c # quelque chose comme ceci:

  SaveBlogInTransaction (blog1);
  SavePostsInTransaction (blog1posts);


maintenant, ma question est la suivante: si l'insertion ne peut être faite qu'à un seul endroit de mon code (il n'y a pas de problèmes de concurrence), est-il garanti que la connexion des publications à leur blog dans la base de données sera valide?


Je veux dire, regardons le schéma de la table des publications:
PostId, PostName, PostType, BlogId

est-il garanti que BlogId sera valide?

remarque: chaque méthode fonctionne comme une transaction et à la fin, elle valide la base de données

.
Était-ce utile?

La solution

Les articles auront l'ID de blog correct même dans votre question reformulée. NHibernate insérera la ligne Blog dans la base de données dès que Save sera appelé et récupérera la valeur d'identité générée à l'aide de SCOPE_IDENTITY à ce moment-là. Cette valeur d'ID sera stockée dans l'objet Blog et sera disponible pour toutes les publications créées ultérieurement.

C’est la raison pour laquelle les utilisateurs disent que les ID basés sur l’identité ne constituent pas un bon choix. NHibernate doit exécuter le code SQL pour insérer la ligne immédiatement afin que la valeur d’identité correcte puisse être obtenue. Si un autre générateur d'identité est utilisé, NHibernate peut éviter d’exécuter les instructions d’insertion SQL tant que la transaction n’est pas validée, car il n’est pas nécessaire de contacter la base de données pour déterminer la valeur de l’ID de l’objet.

Autres conseils

je voudrais poser la question un peu différent. Disons que nous avons ce code:

 
     SaveBlogInTransaction (blog1);
     SaveBlogInTransaction (blog2);
     SavePostsInTransaction (post1_a, post1_b, ...); // tous les articles de blog1
     SavePostsInTransaction (post2_a, post2_b, ...); // tous les articles de blog2
  

est-il garanti que post1_a, post1_b, ... posts 'blogid = blog1id?
est-il garanti que post2_a, post2_b, ... posts 'blogid = blog2id?

Je pense que SCOPE_IDENTITY () ne convient pas ici car nous avons d'abord inséré blog1, blog2 et seulement alors blog1_posts et blog2_posts

remarque: nous avons une relation un à plusieurs dans le modèle, mais dans la base de données, nous n'enregistrons que pour chaque publication. l'identifiant du blog auquel il appartient (nous n'avons pas de table BlogPosts)

Cela dépend de votre cartographie. Si vous avez mappé la relation un à plusieurs de telle sorte que Blog possède une collection de BlogPosts et que BlogPost ait une référence à Blog, vous pouvez créer un blog, ajouter des publications à sa collection BlogPosts et enregistrer uniquement le blog. NHibernate se chargera d'insérer d'abord l'enregistrement du blog, puis de définir la clé étrangère sur les objets enfants avant de les conserver. Cela garantit que BlogId sera valide.

Je n'ai pas consulté le code source de NHibernate, mais je suis sûr qu'il utilise la meilleure pratique pour récupérer l'identité après l'insertion, probablement SCOPE_IDENTITY. Cet article de blog traite des trois méthodes.

Je ne suis pas d'accord pour dire que l'utilisation de l'identité est une mauvaise pratique. Le problème principal avec cela est que NHibernate peut conserver un objet pour récupérer une identité avant que Flush ne soit appelé. Par conséquent, l’insertion peut se produire en dehors d’une transaction et l’enregistrement doit être supprimé manuellement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top