让我先描述一下背景:
在.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。
任何帮助将不胜感激!
答案 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上的解决方案,特别是第一个答案?