【问题标题】:MVC / Repository Pattern - ArchitectureMVC / 存储库模式 - 架构
【发布时间】:2012-11-18 14:12:40
【问题描述】:

我有一个使用 NHibernate 和 ASP.Net MVC 的项目。该应用程序旨在允许用户跟踪某些数据,然后根据输入的数据生成统计视图。到目前为止,我的应用程序的结构如下所示:

NHibernate 层: 包含Repository<T> 和UnitOfWork 类,以及实体映射定义。

核心/服务层:包含通用EntityService 类。目前,这只是通过IUnitOfWork定义事务范围,并与IRepository接口,提供更高级别的数据访问服务。

表示层(MVC 应用程序):尚未实现,但包含通常的东西加上依赖注入。

我有几个问题:

  1. 让我的 MVC 应用程序处理所有层的依赖注入是不是很糟糕?例如,除了将EntityService 实例的依赖注入到控制器中,它还将处理IRepository 的依赖注入到EntityService 类中。服务层是否应该自己处理这个问题,即使这意味着在两个不同的地方执行依赖注入?

  2. 我应该在哪里生成我的统计数据?这个业务逻辑似乎不属于我的服务层,目前它只包含实体类型定义和一个用于修改和访问实体属性的接口。我对此有一些想法,但我不确定我最喜欢哪个:

    • 保持我的服务层不变并创建一个单独的统计项目 - 这完全独立于将要使用的实体类型,这意味着我的 MVC 控制器必须在我的业务实体和我的(大概静态)统计类。这是一个非常巧妙的分离,但可能意味着大量业务逻辑仍保留在表示层中。
    • 创建一个统计项目;但是,在这个项目中的类和我的业务实体之间创建一个紧密耦合。例如,我不会将Reading 对象的值 传递给方法,而是传递整个对象(或将它们定义为扩展方法)。这会将业务逻辑从我的 MVC 应用程序中移出,但紧密耦合似乎有点混乱。
    • 将我的所有业务逻辑保留在我的服务层中。定义EntityService 的强类型子类,因此我的服务既包含特定于实体的业务方法,也包含数据存储方法,同时将实体类本身保持为纯数据容器。为任何通用统计处理创建一个单独的统计项目,并通过我的派生服务类调用其方法。我的服务类有效地将业务功能与IRepository<T> 创建的存储功能相结合。

我对第三个选项犯了错误,但有人有什么想法吗?替代建议?

提前致谢!

【问题讨论】:

    标签: asp.net-mvc-3 nhibernate architecture repository-pattern


    【解决方案1】:

    初步观察:

    我喜欢您描述项目的方式,我只是不明白为什么您的 数据访问层 (DAL) 被称为 NHibernate 层:这与您在其中的所有其他部分都很奇怪没有使用技术名称来描述逻辑层(正确)。所以我建议你将它重命名为 DAL,并用它来从 NHibernate 中抽象出你的应用程序。

    我对您的问题的看法:

    1. 绝对没有。将依赖注入应用于所有层是件好事。几个或它好的原因:

      1.1 测试:您可以模拟 DAL 接口并使用另一个 DI 配置文件对不带 DAL 的服务层进行单元测试。以同样的方式,您可以模拟 Web 控制器层的服务等。

      1.2 不同的 DAL 实现:假设您需要不同的 DAL 实现(NOSQL、SQL 或 LINQ 而不是 NHibernate 等)技术来实现您项目的不同部署或在未来进行扩展。您可以轻松地维护不同的 DI 配置文件。

    2. 您可以在不同的项目中部署相同的层。以同样的方式,您可以拥有一个包含不同图层的项目。我认为它们的关系是正交的:项目描述的是物理(开发时间和运行时间)实现。层是合乎逻辑的。所以最初我会用第三个选项保持简单。 我只是不明白您为什么要针对此选项说以下内容:

    为任何通用统计创建单独的统计项目 通过我的派生服务类处理和调用它的方法。我的 服务类有效地将业务功能与存储合并 由 IRepository 创建的功能。

    我将统计信息视为一项或多项服务,因此您可以将其实现为名称空间,并在服务层内使用类。而且,与任何其他服务一样,您可以注入 DAL 存储库类。而且,与任何其他服务/DAL 一样,模型类可以在不同的服务和 DAL 类之间共享。


    StatsService.AverageReadingFor(Person p, DateTime start, DateTime end) 听起来不错。

    有几个实现选项:

    1. 使用底层存储库功能(例如:SQL avg 函数)
    2. 使用Observer Pattern 也可以使用依赖注入实现
    3. 使用面向方面的编程。以Spring.Net chapter 为例。

    如果您有多个服务层实例(多个服务器),则必须对 2 和 3 进行调整,以便使用消息传递系统进行进程外通信。

    【讨论】:

    • 尝试详细说明我的第二个问题 - 我有一堆 EntityService 类,例如 PersonService 和 ReadingService,它们将我的存储库暴露给我的应用程序。我现在的问题是如何最好地实现类以在Person.IList<Reading> Readings 上生成各种统计信息 - 例如,在我的服务层中使用(作为一个简单的例子)StatsService.AverageReadingFor(Person p, DateTime start, DateTime end) 是否更合适,或者只是在我的服务层中使用Person.Readings.Where(e => e.DateRecorded ... )控制器并在那里平均它们?
    • 顺便感谢您的建议,我已经实现了依赖注入并将我的 NHibernate 层重命名为 DataAccess。
    • 统计是业务逻辑(和功能需求)的一部分,还是您将其用于应用程序监控目的?
    • 它们是功能要求 - 生成实时统计数据将是应用程序功能的核心部分。
    • 谢谢,我会考虑在我的服务层中构建一个统计服务,它与我的实体类紧密耦合。
    【解决方案2】:

    只是一个更新——关于我的第二个问题,我决定定义一个IStatsService<T>,它期望将IEntityService<T> 传递到它的构造函数中。我将把它用于业务实体的通用统计处理,并在我需要更多类型特定信息的地方创建实现IStatsService<T> 的更多接口。

    希望这会帮助那些一直在为类似问题摸不着头脑的人!

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 1970-01-01
      • 2017-03-24
      • 2012-02-13
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多