2010-11-05 7 views
4

Je me demande quelle serait la meilleure conception pour persister une nouvelle entité enfant avec NHibernate sans écraser accidentellement le parent dans la base de données.NHibernate: Comment enregistrer une nouvelle entité sans écraser le parent:

Le problème que j'ai est que l'entité enfant ressemblera à quelque chose comme ceci:

class Child 
{ 
    Parent Parent; 
    // other fields 
} 

Mon problème est que l'enfant a été fourni à partir de la couche d'interface utilisateur ainsi que l'ID du parent, et que des moyens que l'identifiant Parent est fondamentalement non initialisé: il aura l'ID rempli mais tout le reste sera nul - car la seule façon de remplir ses champs serait un aller-retour supplémentaire dans la base de données pour les lire. Maintenant, si j'appelle Session.SaveOrUpdate(child) sur NHibernate, que va-t-il se passer avec le parent? Je ne veux pas que NHibernate cascade sauvegarde le parent non initialisé car cela détruirait simplement les données dans la base de données. Comment les gens abordent ce problème? Des meilleures pratiques?

Répondre

0

Si vos modèles ressemble à ce

class Parent 
{ 

} 


class Child 
{ 
    Parent myParent; 
} 

et que vous essayez de mettre le parent et sauver l'enfant sans avoir un objet parent complet, juste l'ID.

Vous pouvez essayer ceci:

session.Lock(child.myParent, LockMode.None); 

avant d'enregistrer, cela devrait dire NHibernate qu'il n'y a pas de changement à l'objet parent Persister et il ne devrait regarder l'objet pour l'Id de persister l'association entre Parent et enfant

1

Vous devriez probablement travailler avec la racine agrégée (probablement le parent) lorsque vous faites des sauvegardes (ou SaveOrUpdates etc).

Pourquoi ne pas simplement:

  • Fetch l'objet parent en utilisant l'ID parent que vous avez dans l'enfant de la couche d'interface utilisateur
  • Ajouter l'enfant à la collecte des enfants »des parents
+0

OK merci.Cela impliquerait un aller-retour supplémentaire dans la base de données pour récupérer le parent, même si je n'ai pas l'intention de faire quoi que ce soit avec les données parentes, ce que j'aurais préféré éviter. Il n'y a pas de bon moyen d'éviter cela? – PhantomDrummer

+0

Utilisez Load() comme Trygve suggéré pour éviter de charger des données inutiles. – UpTheCreek

+1

Il semble que ce qui se passe est que les enfants sont remplis directement dans l'interface utilisateur par une requête sans tenir compte du parent. Ce qui est suggéré est un principe général de conception dans lequel vous n'avez jamais d'enfants en dehors du parent. Vous n'ajoutez certainement pas de nouveaux enfants sans passer par le parent. – Sisyphus

3

Vous devez utiliser le fichier session.Load (parentid) pour obtenir la racine agrégée. Contrairement à la méthode session.Get(), elle ne récupère aucune donnée de la base de données, elle instancie simplement un objet proxy Parent utilisé pour ajouter des objets Child au parent correct dans la base de données (par exemple, obtenir la clé étrangère correctement) .

Votre code ressemblerait probablement quelque chose comme:

// Set the Parent to a nhibernate proxy of the Parent using the ParentId supplied from the UI 
childFromUI.Parent = Session.Load<Parent>(childFromUI.Parent.Id); 
Session.Save(childFromUI); 

This article explains Get/Load and the nhibernate caches really well

+0

+1; lien intéressant, mais j'ai trouvé http://ayende.com/Blog/archive/2009/04/30/nhibernate-ndash-the-difference-between-get-load-and-querying-by.aspx une référence plus concise sur les différences sur Get vs Load. – Marijn

+0

Intéressant, merci – PhantomDrummer

1

Je pense que vous devez donner un aperçu de votre configuration de mappage pour nhibernate. Si vous avez défini sur la référence par l'enfant au parent qu'il doit tout Cascade, il le mettra à jour! Donc, si vous dites Cascade.None il ne fera rien. Tous les autres sont de mauvaises idées. Parce que vous avez déjà les informations de ce parent. Alors pourquoi lire de db agane ?!

Questions connexes