1

我有一个项目,我在其中使用NHibernate和ASP.Net MVC。该应用程序旨在允许用户跟踪某些数据,然后根据输入的数据生成统计数据视图。我的应用程序的结构到目前为止看起来是这样的:MVC /知识库模式 - 体系结构

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

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

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

我有几个问题:

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

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

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

我犯错朝着第三个选项,但没有任何人有什么想法?替代建议?

在此先感谢!

回答

3

初步观察:

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

我对你的问题发表意见:

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

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

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

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

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

我将统计看作一个或多个服务,因此您可以将其作为名称空间与服务层中的类一起实现。而且,与其他服务一样,您可以注入DAL Repository类。而且,与任何其他Service/DAL一样,Model类可以在不同的Services和DAL类之间共享。


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

有几种实施选项:

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

如果您有多个服务层实例(多于一个服务器)比2和3必须适用于使用消息传递系统的进程间通信。

+0

试着对第二个问题进行一点说明 - 我有一堆EntityService类,例如PersonService和ReadingService,它们将我的存储库暴露给我的应用程序。我的问题是现在如何最好地实现类来产生'Person.IList Readings'的各种统计信息 - 例如,是否更适合(作为一个简单的例子)'StatsService.AverageReadingFor(Person p,DateTime start,DateTime end)'在我的服务层中,或者只是在我的控制器里面使用Person.Readings.Where(e => e.DateRecorded ...)'并在那里平均它们? –

+0

感谢您的建议,我已经实现了我的依赖注入并将我的NHibernate层重命名为DataAccess。 –

+0

统计数据是业务逻辑(和功能需求)的一部分还是用于应用程序监控目的? –

0

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

希望这会帮助那些一直在摸索类似问题的人!