NHibernate:“懒得初始化......”,DDD方法

时间:2009-09-21 18:58:29

标签: asp.net-mvc nhibernate domain-driven-design

我正在尝试使用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所描述的内容。我只是无法弄清楚如何在基础设施层实现它,或者它应该在哪里实现?

提前致谢。任何帮助将不胜感激!

3 个答案:

答案 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了解实施情况。