2009-11-04 2 views
1

Considérant les blocs de code suivants, pourquoi l'appel à HQL fonctionne-t-il mais l'appel à delete() ne fonctionne pas? En arrière-plan, j'utilise le pilote NHibernate sur IBM.Data.DB2.Iseries. Venez découvrir, la journalisation sur l'AS400 est désactivée, donc je ne peux pas utiliser les transactions. Je ne suis pas l'administrateur AS400 ou ne sais rien à ce sujet, donc je ne sais pas si la journalisation désactivée (pas l'ouverture des transactions) est à l'origine de ce problème ou non. Dois-je absolument avoir la possibilité d'ouvrir des transactions si j'appelle Delete() ou d'autres fonctions de NHibernate?NHibernate - Pourquoi l'appel à Delete() échoue-t-il à supprimer mais à supprimer via HQL?

//This Does not work - no error and no deletes 
public static void Delete(Object Entity) 
    { 
     using (ISession session = _sessionFactory.OpenSession()) 
     { 
      //using(ITransaction tx = session.BeginTransaction()) 
      //{ 
       session.Delete(Entity); 
       //tx.Commit();      
       session.Close();      
      //} 
     } 
    } 

//This does work 
public static void Delete(Object Entity) 
    { 
     using (ISession session = _sessionFactory.OpenSession()) 
     { 
      //commented out transaction control because throws error because 
      //journaling is not turned on the AS400 
      //using(ITransaction tx = session.BeginTransaction()) 
      //{ 
       session.CreateQuery("delete MyDAO p where p.MyDAOID = :MyDAOID").SetString("MyDAOID", ((MyDAO)Entity).MyDAOID.ToString()).ExecuteUpdate();     
      //} 
     } 
    } 
+0

Avez-vous une exception et quel est le message? Si vous ne recevez pas d'exception, quel sql sera généré par session.delete? – Paco

+0

Paco, je ne reçois pas d'exception et aucune requête de suppression n'est générée. S'il vous plaît voir mon autre réponse à ce poste (j'ai posté après avoir vu votre commentaire). Si j'appelle la fonction Get pour extraire l'objet dans une session, puis lui dire de le supprimer dans cette session, il génère alors la requête Delete. –

+0

Alors, pourquoi je ne reçois pas d'exception? J'apprends cela, parce que j'ai demandé une liste d'objets dans une session puis que je l'ai fermée, et que j'essaie de supprimer l'objet d'une session différente, ça ne fonctionne pas - parce que je ne le trouve pas dans la même unité de travail. Cependant, ne devrait-il pas être assez gentil à lancer et exception donc je sais que mon objet n'a pas supprimé? –

Répondre

6

Essayez d'appeler session.Flush() après la suppression, mais avant de fermer la session. Et vous n'avez pas besoin de fermer explicitement la session:

using (var session = ...) 
{ 
    entity.Delete(); 
    session.Flush(); 
} 
+0

Cela n'a pas fonctionné mais merci pour le conseil. –

+0

Cela a fonctionné pour moi, et j'aimerais savoir pourquoi. J'utilise la même session pour obtenir toutes mes entités. J'ai l'impression que c'est parce qu'il est plus rare que la suppression ait lieu avant que la transaction ne soit validée. NHibernate a probablement l'intention de tout faire plus tard, ce qui serait normalement acceptable. – DustinA

1

Après fouillant plus loin dans, je trouve que cela fonctionne mais pourquoi ?:

public static void Delete(Object Entity) 
{ 
    using (ISession session = _sessionFactory.OpenSession()) 
    {  
     MyDAO p = session.Get<MyDAO>(Entity.ID); 
     session.Delete(p); 
     session.Flush();          
    }    
} 

Voici mon scénario: je précédemment interrogé pour une liste d'objets que j'ai peuplé dans une grille. Pour ce processus de requête, j'ai ouvert/fermé une session. En appelant ma fonction de suppression, je prends cet objet et le passe dans cette fonction pour un processus de session d'ouverture/fermeture séparé. Pour remuer un peu les choses, j'ai ajouté l'appel à cette nouvelle suppression en lui demandant d'obtenir l'objet en premier (celui que je veux supprimer), puis en appelant la suppression. Maintenant, il envoie la requête de suppression à la base de données et l'objet est en fait supprimé. Pourquoi est-ce? Est-ce parce que ma requête originale d'objets a été ouverte dans une session différente et ensuite supprimée dans une autre session? Est-ce que cela a quelque chose à voir avec l'unité de travail? Devrais-je ouvrir ma session pour ma grille, la laisser ouverte jusqu'à ce que mon formulaire se ferme afin que tous les suppressions fonctionnent dans cette session? J'avais l'impression que les sessions devraient être ouvertes/fermées rapidement. Je suis confus.

+1

1. Vous ne devez pas ouvrir une nouvelle session pour chaque méthode d'accès aux données. Vous devez en ouvrir un nouveau chaque fois qu'un utilisateur clique sur un bouton de sauvegarde ou de suppression dans l'interface utilisateur. Utilisez une session par unité de travail. Lorsque vous ne le faites pas, vous perdez la mise en cache de la session et vous devez à nouveau attacher les objets récupérés par les sessions précédentes à la session. 2. Vous pouvez changer l'usine de session pour "auto-flush" – Paco

+0

Désolé mais je suis confus par le point 1 de votre commentaire. Vous déclarez que je ne devrais pas ouvrir une nouvelle session pour chaque méthode d'accès aux données, mais vous déclarez que je devrais pour chaque sauvegarde/suppression qui dans ma terminologie sont des méthodes d'accès aux données. Précisez s'il vous plaît. Alors, qu'est-ce qui est considéré comme une unité de travail lorsqu'on travaille avec un formulaire qui a une grille? Est-ce que l'un est en train d'interroger les données et l'autre est la suppression des données ou est-ce que l'interrogation des données et la suppression/modification (une donnée ou toutes) sont?J'ai tenté d'ouvrir une session, interroger mes données/remplir ma grille, supprimer puis vider, et cela a fonctionné. –

+0

Je ne peux pas vous donner une réponse à cela: cela peut être à la fois en fonction de ce que les données sont et ce que l'utilisateur fait avec. Martin Fowler écrit à ce sujet dans Patterns of Entrerprice Applications – Paco

Questions connexes