2010-07-29 4 views
1

Permettez-moi de décrire le contexte d'abord:ObjectDataSource de ASP.NET et NHibernate gestion de session

Dans un projet .NET C#, j'utilise NHibernate pour faire le lien entre les objets C# et le modèle de base de données. J'ai cartographié mes objets avec NHibernate Mapping Attibutes.

J'ai écrit des requêtes d'accès aux données dans HQL, tous étant isolés dans des méthodes individuelles, décorées avec des attributs pour la gestion des transactions. Voici comment mes classes d'accès aux données ressemblent à:

namespace MyProject.DataAccess 
{ 
    public class ClientDao 
    { 
     private ISessionFactory sessionFactory; 
     public ISessionFactory SessionFactory 
     { 
      protected get { return sessionFactory; } 
      set { sessionFactory = value; } 
     } 

     protected ISession CurrentSession 
     { 
      get { return sessionFactory.GetCurrentSession(); } 
     } 

     [Transaction(TransactionPropagation.Required, IsolationLevel.ReadCommitted)] 
     public IList<Client> GetAll() 
     { 
      return CurrentSession.CreateQuery("from Client c").List<Client>(); 
     } 
    }  
} 

J'ai configuré la session NHibernate et la gestion des transactions avec le printemps. Voici la configuration xml:

<!-- NHibernate Configuration --> 
<object id="NHibernateSessionFactory" type="GeSuiPro.Abstract.ExtendedSessionFactoryObject, GeSuiPro.Abstract"> 
    ... 

    <property name="HibernateProperties"> 
    ... 
    </property> 

    <!-- provides integation with Spring's declarative transaction management features --> 
    <property name="ExposeTransactionAwareSessionFactory" value="true" /> 
</object> 

<!-- Transaction Management Strategy - local database transactions --> 
<object id="transactionManager" 
    type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate21"> 

    <property name="DbProvider" ref="DbProvider"/> 
    <property name="SessionFactory" ref="NHibernateSessionFactory"/> 

</object> 

<tx:attribute-driven transaction-manager="transactionManager"/> 

<!-- Exception translation object post processor --> 
<object type="Spring.Dao.Attributes.PersistenceExceptionTranslationPostProcessor, Spring.Data"/> 

Maintenant, quand je tente d'accéder à la session à partir du code C#, tout fonctionne bien:

IList<Client> list = clientDao.GetAll(); 

Cependant, certains appels aux méthodes "getAll" sont fait à partir du code ASP via des objets ObjectDataSource:

<asp:ObjectDataSource ID="odsClient" runat="server" TypeName="MyProject.DataAccess.ClientDao" 
      SelectMethod="GetAll" DataObjectTypeName="MyProject.Object.Client" /> 

Lorsque vous accédez à l'objet « currentSession » dans ma méthode de GetAll, je reçois l'erreur suivante: « Pas de mise en veille prolongée sess ion lié à fil, et la configuration ne permet pas la création de non-transactionnel ici ". Il semble que quelque chose manque à ma configuration.

Pour plus d'informations, j'utilise .NET Framework 3.5 avec NHibernate 2.1.2. Ma base de données est Oracle 11g.

Toute aide serait appréciée!

Répondre

1

Ok, je pense que je l'ai trouvé ce qui va mal. Le fait est que je n'ai pas commencé à coder à partir de zéro. J'avais déjà un projet en cours, mais j'ai dû reconstruire l'accès aux données pour que le projet fonctionne avec plusieurs SGBD. Ainsi, j'ai utilisé NHibernate. Comme je ne suis pas la personne qui a lancé le projet, je n'ai pas une connaissance à 100% de ce qui a été fait jusqu'à maintenant, donc il y avait un morceau de code que NHibernate n'a pas aimé. Par exemple, il y avait un cas où un objet avec un identifiant donné a été chargé par la session NHibernate, et ailleurs dans le code, l'objet a été recréés puis mis à jour:

MyObject a = session.createQuery("from MyObject m where m.Id = 0"); 

Et ailleurs dans le code:

MyObject a = new MyObject(); 
a.Id = 0; 
session.Update(a); 

Cela rend malade NHibernate parce que la même session est titulaire de deux entités du même type avec le même identifiant.

0

Avez-vous essayé la solution sur le fil Spring/Hibernate/JUnit - No Hibernate Session bound to Thread, en particulier la première réponse?

+0

Merci pour votre réponse. Je ne pense pas que cette solution soit appropriée, car j'ai déjà défini un gestionnaire de transactions. Je peux me tromper, mais il semble que cette solution est de travailler avec JUnit seulement. De plus, mon problème est d'accéder à la session NHibernate avec un appel du code ASP.NET, car cela fonctionne très bien à partir du code C#. – Hal

2

juste pour être sûr, votre classe ClientDao est gérée Spring droite? Donc, quand vous l'utilisez à partir de C# tout est OK. Mais votre ObjectDadaSource instanciera un nouvel objet ClientDao utilisant la réflexion (en dehors du printemps) afin que vous n'avez pas ce que vous voulez (pas DI, aucune procuration AOP pour les transactions).

Vous pouvez

  • utiliser l'événement ObjectCreating de la classe ObjectDataSource pour obtenir l'objet de la ApplicationContext (plus ici: http://www.rain-works.com/wpblog/index.php/2009/07/how-to-use-aspnet-object-data-source-with-ioc-spring-framework/)

  • envelopper les appels à l'objet DAO dans les méthodes statiques une classe statique qui "connaît" Spring et qui utilise ces méthodes statiques dans ObjectDataSource (aucun objet n'est créé par DataSourceObject avec des méthodes statiques)

  • w riter votre propre contrôle ObjectDataSource "Spring" personnalisé qui obtiendra automatiquement l'objet dao à partir du ApplicationContext. Cette façon de faire est très flexible et vous pouvez également gérer la pagination, le tri d'une manière très efficace lors de la liaison à un gridview. Vous pouvez définir de nombreux moyens de transmettre des arguments à vos méthodes dao pour l'interrogation des données (à partir de la session, de l'expression du ressort, d'autres services printaniers, etc.). Mais c'est plus difficile et nécessite un peu de codage en premier ...

Hope this helps

+0

Comportement étrange ... – Hal