我正在尝试使用DDD方法在ASP.NET MVC应用程序中设置NHibernate。但是,在尝试延迟加载与对象相关的实体时,我确实收到错误。以下是我如何构建我的应用程序:
基础架构层: 包含映射文件,存储库实现和NHibernate引导程序,以配置和构建会话工厂。
下面是一个存储库示例:
public class CustomerRepository : ICustomerRepository
{
public Customer GetCustomerById(int customerId)
{
using (var session = NHibernateBootstrapper.OpenSession())
return session.Get<Customer>(customerId);
}
}
域层 有简单的POCO类,存储库和服务接口
应用层: 包含服务实现。
以下是一个服务示例:
public class CustomerService : ICustomerService
{
private ICustomerRepository _repository;
public CustomerService(ICustomerRepository repository)
{
_repository = repository;
}
public Customer GetCustomerById(int customerId)
{
return _repository.GetCustomerById(customerId);
}
}
演示文稿图层 包含ASP.NET MVC应用程序。这就是我发现问题的地方。 使用MVC方法,我有一个控制器,它使用CustomerService服务获取客户并在View中显示客户(强类型)。这个客户有一个相关的实体Contact,当我尝试使用Model.Contact在我的View中访问它时,Model是我的Customer对象,我得到一个LazyInitializationException。
我知道为什么我会这样做。这是因为用于在CustomerRepository中检索Customer的会话现在已经过时了。我的问题是如何解决这个问题。我想如果我可以避免在我的存储库中获取客户的相关联系人实体,因为某些视图只需要客户数据,而不是联系人数据。如果可以的话呢?
所以问题是:是否可以等待查询数据库,直到表示层需要相关实体联系?
我认为我需要的是这个article所描述的内容。我只是无法弄清楚如何在基础设施层实现它,或者它应该在哪里实现?
提前致谢。任何帮助将不胜感激!
答案 0 :(得分:2)
对于会话管理,每个请求使用单个会话是很常见的。您可以看到实施here的示例。它是一个开源项目,旨在在Nhibernate的帮助下轻松设置新的asp.net应用程序。源代码可以创建here。
希望它有所帮助。
答案 1 :(得分:1)
我也推荐Sharp Architecture。
另一种方法和建议是避免将实体传递给视图。除了会话管理之外还有其它问题 - 业务规则泄漏到视图中,膨胀/ spagetti代码等等。使用ViewModel方法。
您将获得的另一个问题是将您的实体存储在Session中。一旦您尝试从会话[“客户”]获得客户,您将获得相同的例外。有几个解决方案,例如存储ID,或添加存储库方法以防止延迟加载您将要存储在会话中的对象 - 读取NHibernate的SetFetchMode - 当然,您也可以使用它来将实体传递给观点。但正如我所说,你最好坚持使用ViewModel方法。 Google for ViewModel,或参考ASP.NET MVC In Action一书,该书使用了来自http://code.google.com/p/codecampserver/的代码示例。另请阅读this,例如。
答案 2 :(得分:0)
您的Customer类中的所有属性和方法都标记为virtual
吗?
您是如何开启和关闭会话的?我使用名为ActionFilterAttribute
的{{1}}并用它装饰我的所有控制器。
查看this了解实施情况。