我有一个C# .Net网络服务。我正在调用一个使用nHibernate连接到我的数据库的dll (C# .Net)。当我调用dll时,它执行对db的查询,并加载父对象"Task“。但是,当dll尝试访问子对象"Task.SubTasks“时,它抛出以下错误:
NHibernate.HibernateException failed to lazily initialize a collection of role: SubTasks no session or session was closed我是nHibernate的新手,所以不确定我遗漏了哪段代码。
在调用dll之前,是否需要在web服务中启动Factory会话?如果是这样,我该怎么做呢?
编辑:添加了web服务代码和CreateContainer()方法代码。此代码在调用dll之前被调用
[WebMethod]
public byte[] GetTaskSubtask (string subtaskId)
{
var container = CreateContainer(windsorPath);
IoC.Initialize(container);
//DLL CALL
byte[] theDoc = CommonExport.GetSubtaskDocument(subtaskId);
return theDoc;
}
/// <summary>
/// Register the IoC container.
/// </summary>
/// <param name="aWindsorConfig">The path to the windsor configuration
/// file.</param>
/// <returns>An initialized container.</returns>
protected override IWindsorContainer CreateContainer(
string aWindsorConfig)
{
//This method is a workaround. This method should not be overridden.
//This method is overridden because the CreateContainer(string) method
//in UnitOfWorkApplication instantiates a RhinoContainer instance that
//has a dependency on Binsor. At the time of writing this the Mammoth
//application did not have the libraries needed to resolve the Binsor
//dependency.
IWindsorContainer container = new RhinoContainer();
container.Register(
Component.For<IUnitOfWorkFactory>().ImplementedBy
<NHibernateUnitOfWorkFactory>());
return container;
}编辑:添加DLL代码和存储库代码...
DLL代码
public static byte[] GetSubtaskDocument(string subtaskId)
{
BOESubtask task = taskRepo.FindBOESubtaskById(Guid.Parse(subtaskId));
foreach(subtask st in task.Subtasks) <--this is the line that throws the error
{
//do some work
}
}任务存储库
/// <summary>
/// Queries the database for the Subtasks whose ID matches the
/// passed in ID.
/// </summary>
/// <param name="aTaskId">The ID to find matching Subtasks
/// for.</param>
/// <returns>The Subtasks whose ID matches the passed in
/// ID (or null).</returns>
public Task FindTaskById(Guid aTaskId)
{
var task = new Task();
using (UnitOfWork.Start())
{
task = FindOne(DetachedCriteria.For<Task>()
.Add(Restrictions.Eq("Id", aTaskId)));
UnitOfWork.Current.Flush();
}
return task;
}子任务的存储库
/// <summary>
/// Queries the database for the Subtasks whose ID matches the
/// passed in ID.
/// </summary>
/// <param name="aBOESubtaskId">The ID to find matching Subtasks
/// for.</param>
/// <returns>The Subtasks whose ID matches the passed in
/// ID (or null).</returns>
public Subtask FindBOESubtaskById(Guid aSubtaskId)
{
var subtask = new Subtask();
using (UnitOfWork.Start())
{
subtask = FindOne(DetachedCriteria.For<Subtask>()
.Add(Restrictions.Eq("Id", aSubtaskId)));
UnitOfWork.Current.Flush();
}
return subtask;
}发布于 2012-04-28 00:59:51
显然,您已经在某个NHibernate数据类中映射了一个集合,并启用了延迟加载(或者更好:没有禁用,因为这是默认行为)。NHibernate加载实体并为映射的集合创建代理。一旦它们被访问,NHibernate就会尝试加载该集合的项。但是,如果您在此之前关闭您的NHibernate会话,您收到的错误将会发生。您可能会通过web服务将数据对象公开给web服务客户端。在序列化过程中,XmlSerializer会尝试序列化集合,这会提示NHibernate对其进行填充。当会话关闭时,就会出现错误。
有两种方法可以防止这种情况发生:
后关闭会话
或
以上编辑后的新增内容:
在您的存储库中,您可以在using-statement中启动UnitsOfWork。一旦代码完成,它们就会被处理掉。我不知道UnitOfWork的实现,但我假设它控制着NHibernate会话的生命周期。通过释放UnitOfWork,您可以通过关闭NHibernate会话来侦测。当您的映射初始化延迟加载的集合时,这些集合尚未填充,因此会发生错误。NHibernate需要加载实体的会话的确切实例来填充延迟初始化的集合。
如果您使用延迟加载,并且有一个在响应完成之前关闭会话的存储库,那么您将遇到这样的问题。一种选择是在请求开始时初始化UnitOfWork,并在响应完成后关闭它(例如,在Application_BeginRequest中是Application_EndRequest,在Global.asax.cs中是Application_EndRequest)。当然,这意味着要将存储库紧密集成到web服务中。
在任何情况下,为单个请求创建一个与延迟加载相结合的会话都不是一个好主意,而且在未来很可能会产生类似的问题。如果您不能更改存储库实现,则可能必须禁用延迟加载。
发布于 2012-04-28 05:10:08
使用Garland的反馈,我解决了这个问题。我从DLL中的存储库中删除了UnitOfWork代码,并将对DLL的Web Service调用包装在UnitOfWork中,请参阅下面的代码模块:
Web服务
[WebMethod]
public byte[] GetSubtaskDocument (string subtaskId)
{
var container = CreateContainer(windsorString);
IoC.Initialize(container);
byte[] theDoc;
using (UnitOfWork.Start())
{
//DLL call
theDoc = CommonExport.GetSubtaskDocument(subtaskId);
UnitOfWork.Current.Flush();
}
return theDoc;
}DLL中的存储库调用
public Subtask FindSubtaskById(Guid aSubtaskId)
{
return FindOne(DetachedCriteria.For<Subtask>()
.Add(Restrictions.Eq("Id", aSubtaskId)));
}https://stackoverflow.com/questions/10354663
复制相似问题