2010-01-08 2 views
7

Dans this question J'ai demandé à propos de la durée de vie de la session NHibernate. J'utilise une application de bureau, mais avec une séparation client/serveur, donc la conclusion est que j'utiliserai une requête par serveur, car c'est du côté serveur que se passe toute la magie de NHibernate.Comment gérer la durée de vie d'une session NHibernate en utilisant des services?

Mon problème maintenant est de savoir comment le gérer. J'ai eu problems before avec le chargement de données référencées lorsque la session est prématurément fermée. Le problème est que je vois ce qui suit sur mes classes référencées lors du débogage - d'où les données référencées n'est pas encore chargé:

base de

{} = {NHibernate.HibernateException "Initialiser [MyNamespace.Foo # 14] -failed pour initialiser paresseusement une collection de rôle: MyNamespace.Foo.Bars, aucune session ou session fermée "}

d'après ce que je comprends qu'il ne se charge pas tout, même si je commets la transaction. J'ai donc appris que je devais garder ma session ouverte pendant un certain temps, mais combien de temps? Ma question est fondamentalement si je gère correctement la durée de vie, ou ce que je devrais changer pour être sur la bonne voie. Honnêtement, je ne vois pas comment cela peut être faux, donc ce que j'aimerais vraiment, c'est un appel de fonction pour m'assurer que les données référencées sont récupérées. Je suis pas en utilisant le chargement paresseux, alors je pensais qu'ils seraient chargés immédiatement ..?

Architecture actuelle: Utilisation d'une classe "comportement de service" effectuant la transaction. Ceci est IDisposable, donc le service lui-même utilise une clause d'utilisation. La NHibernateSessionFactory fournit une usine statique qui sera donc réutilisée.

// This is the service - the function called "directly" through my WCF service. 
public IList<Foo> SearchForFoo(string searchString) 
{ 
    using (var serviceBehavior = new FooServiceBehavior(new NhibernateSessionFactory())) 
    { 
     return serviceBehavior.SearchForFoo(searchString);  
    }       
} 

public class FooServiceBehavior : IDisposable 
{ 
    private readonly ISession _session; 

    public FooServiceBehavior(INhibernateSessionFactory sessionFactory) 
    { 
     _session = sessionFactory.OpenSession();     
    } 

    public void Dispose() 
    { 
     _session.Dispose(); 
    } 

    public IList<Foo> SearchForFoo(string searchString) 
    {   
     using (var tx = _session.BeginTransaction()) 
     { 
      var result = _session.CreateQuery("from Foo where Name=:name").SetString("name", searchString).List<Name>(); 
      tx.Commit(); 
      return result; 
     } 
    } 

Répondre

5

Il s'avère que je fais du chargement paresseux après tout. J'ai eu la correspondance suivante:

public class FooMapping : ClassMap<Foo> 
{ 
    public FooMapping() 
    { 
     Not.LazyLoad(); 
     Id(c => c.Id).GeneratedBy.HiLo("1"); 
     Map(c => c.Name).Not.Nullable().Length(100); 
     HasMany(x => x.Bars).Cascade.All(); 
    } 
} 

Je supposais le chargement paresseux handicapés Not.LazyLoad(), mais apparemment pas pour les objets référencés. J'ai ajouté un chargement paresseux sur la référence, et cela semble avoir résolu le problème.

public class FooMapping : ClassMap<Foo> 
{ 
    public FooMapping() 
    { 
     Not.LazyLoad(); 
     Id(c => c.Id).GeneratedBy.HiLo("1"); 
     Map(c => c.Name).Not.Nullable().Length(100); 
     HasMany(x => x.Bars).Not.LazyLoad(); // <---------- 
    } 
} 

Merci pour votre temps, et je serai toujours heureux de voir vos opinions à savoir si ma structure donnée est raisonnable.

-1

Si des fichiers xml sont utilisés à des fins de mappage, nous pouvons définir lazy = false pour le sac.

+0

Les fichiers XML ne sont pas utilisés pour le mappage - comme vous pouvez le voir dans l'exemple de code. J'utilise Fluent pour les mappings. – stiank81

Questions connexes