【问题标题】:NHibernate: "failed to lazily initialize...", DDD approachNHibernate:“无法延迟初始化...”,DDD 方法
【发布时间】:2010-11-30 04:24:54
【问题描述】:

我正在尝试使用 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 服务获取客户并在视图中显示客户(强类型)。此客户有一个相关实体联系人,当我尝试使用 Model.Contact 在我的视图中访问它时,其中 Model 是我的客户对象,我得到一个 LazyInitializationException。

我知道我为什么会得到这个。这是因为用于在 CustomerRepository 中检索客户的会话现在已经死了。我的问题是如何解决这个问题。我想是否可以避免在我的存储库中获取客户的相关联系人实体,因为某些视图只需要客户数据,而不需要联系人数据。如果这可能吗?

那么问题来了:是否可以等待查询数据库,直到表示层需要相关实体Contact?

我认为我需要的是 article 所描述的内容。我只是不知道如何在基础设施层实现它,或者它应该在哪里实现?

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

【问题讨论】:

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


    【解决方案1】:

    对于会话管理,每个请求使用单个会话是很常见的。您可以看到一个实现示例here。这是一个开源项目,旨在借助 Nhibernate 轻松设置新的 asp.net 应用程序。源代码可以创建here

    希望对你有帮助。

    【讨论】:

      【解决方案2】:

      我也推荐夏普架构。

      另一种方法和建议是避免将实体传递给视图。除了会话管理之外,它还有其他问题 - 业务规则泄漏到视图中,那里的臃肿/spagetti 代码等等。使用 ViewModel 方法。

      您会遇到的另一个问题是将实体存储在 Session 中。一旦您尝试从 Session["customer"] 获取客户,您将获得相同的异常。有几种解决方案,例如存储 ID,或添加存储库方法以防止延迟加载要存储在会话中的对象 - 阅读 NHibernate 的 SetFetchMode - 当然,您也可以使用它来传递实体到意见。但正如我所说,您最好坚持使用 ViewModel 方法。 Google for ViewModel,或参考 ASP.NET MVC In Action 这本书,它使用来自http://code.google.com/p/codecampserver/ 的代码示例。例如,另请阅读this

      【讨论】:

        【解决方案3】:

        您的 Customer 类中的所有属性和方法是否都标记为 virtual

        您如何打开和关闭会话?我使用了一个名为TransactionPerRequestActionFilterAttribute 并用它来装饰我所有的控制器。

        查看this 以了解实施情况。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-19
          • 1970-01-01
          • 1970-01-01
          • 2016-07-06
          • 2015-07-02
          相关资源
          最近更新 更多