ASP.NET的ObjectDataSource和NHibernate会话管理

时间:2010-07-29 12:12:08

标签: c# .net asp.net nhibernate spring.net

让我先描述一下背景:

在.NET C#项目中,我使用NHibernate来建立C#对象和数据库模型之间的链接。我已经用NHibernate Mapping Attibutes映射了我的对象。

我已经在HQL中编写了数据访问查询,所有这些查询都以单独的方法隔离,这些方法使用事务管理的属性进行修饰。以下是我的数据访问类的样子:

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>();
         }
    }    
}

我已经使用Spring配置了Nhibernate会话和事务管理。这是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"/>

现在,当我尝试从C#代码访问会话时,一切正常:

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

但是,对“GetAll”方法的一些调用是通过ObjectDataSource对象从ASP代码中进行的:

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

访问GetAll方法中的“CurrentSession”对象时,出现以下错误: “没有Hibernate会话绑定到线程,配置不允许在这里创建非事务性的”。 似乎我的配置中缺少某些东西。

有关信息,我使用.NET 3.5 Framework和NHibernate 2.1.2。我的数据库是Oracle 11g。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

只是为了确定,您的ClientDao类是Spring管理的吗?所以当你从C#中使用它时一切都还可以。 但是你的ObjectDadaSource将使用反射(在Spring之外)实例化一个新的ClientDao对象,因此你没有你想要的东西(没有DI,没有用于事务的AOP代理)。

你可以

  • 使用ObjectDataSource类的事件ObjectCreating从ApplicationContext获取对象(更多信息:http://www.rain-works.com/wpblog/index.php/2009/07/how-to-use-aspnet-object-data-source-with-ioc-spring-framework/

  • 在一个“知道”Spring的静态类的静态方法中包装对DAO对象的调用,而不是在ObjectDataSource中使用这些静态方法(没有对象是由DataSourceObject用静态方法创建的)

  • 编写自己的自定义“Spring”ObjectDataSource控件,它将自动从ApplicationContext获取dao对象。这种方式非常灵活,您还可以在链接到gridview时以非常有效的方式管理分页,排序。您可以定义很多方法将参数传递给dao方法以查询数据(来自会话,spring表达式,其他spring服务等)。但它更难,需要先编码......

希望这有帮助

答案 1 :(得分:1)

好的,我想我发现了什么问题。事实是我还没有开始从头编写代码。我有一个已经在工作的项目,但我必须重新构建数据访问才能使项目与多个SGBD一起工作。因此,我使用了NHibernate。因为我不是开始这个​​项目的人,所以我对目前已经完成的工作没有100%的了解,所以有一些NHibernate不喜欢的代码。 例如,有一种情况是NHibernate会话加载了具有给定Id的对象,并且代码中的其他地方,该对象被重新创建然后更新:

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

代码中的其他地方:

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

这使得NHibernate生病了,因为同一个会话拥有两个具有相同Id的相同类型的实体。

答案 2 :(得分:0)

您是否尝试过线程Spring / Hibernate / JUnit - No Hibernate Session bound to Thread上的解决方案,特别是第一个答案?