NHibernate和存储库的架构

时间:2010-04-13 18:29:55

标签: asp.net nhibernate asp.net-mvc-2

我一直在阅读MVC 2和推荐的模式,到目前为止,我已经得出结论(在很多头发拉动和完全混乱中):

  • 模型 - 只是一个基本数据容器
  • 存储库 - 提供数据访问
  • 服务 - 提供业务逻辑并充当Controller的API

Controller与服务对话,服务与存储库和模型进行对话。例如,如果我想显示带有评论的博客帖子页面,我可能会这样做:

post = PostService.Get(id);
comments = PostService.GetComments(post);

或者,我会这样做:

post = PostService.Get(id);
comments = post.Comments;

如果是这样,从存储库中设置的位置是什么?它没有延迟加载的问题..这不是一个大问题,但后来说我想列出10个帖子,每个帖子的前2个评论,id必须加载帖子然后循环并加载评论变得凌乱。

所有示例都使用“InMemory”存储库进行测试,并说包含db内容将超出范围。但是这给我留下了许多空白,所以一开始有人可以评论上面的内容吗?

1 个答案:

答案 0 :(得分:1)

post = PostService.Get(id);
comments = post.Comments;

像这样遍历模型是可以实现的,也是可取的。你是完全正确的,虽然它是一个性能价格的实现理想,特别是在处理集合时(并且在分层数据结构方面你不会留下任何头发)。

您需要配置NH映射以进行批量延迟加载。 (fetch = subselect batch-size =#),否则急切加载会拉回太多数据,延迟加载会导致N + 1选择问题(1个查询来获取帖子,+ N个查询来获取注释,其中N是帖子的数量 - 你的循环)。

如果您的要求确实是为每个帖子显示2条评论,那么批量大小为2,但毫无疑问您已经猜到,只要您的应用尝试访问第3条评论,NH就会执行另一个选择用另外2个来填充评论集合,因此您可能希望从一开始就有更大的批量大小。在了解用例时计划性能调整阶段。如果您正在开发通用数据访问API,这可能非常困难。 (另外,您需要在评论集合映射中添加order-by =“SOME_COLUMN_NAME”以控制如何获取“第一个”评论)。很容易低估NH映射设置的重要性; ORM解决了许多开发问题,但增加了一个新的世界。

Eric Evans的“领域驱动设计”定义了存储库模式&服务。它们并不总是合适的。除了非常复杂的项目之外,我已经停止使用它们了,很少在MVC版本上使用它们。存储库模式和优势的好处;服务是架构组件的分离,隔离,可测试性和灵活性。在现实世界中 - 考虑您的'使用'命名空间。如果你宁愿避免在你的控制器中使用'nhibernate',那么将它隐藏在存储库中,只需引用repo程序集。

这与可测试性相关 - 您可以独立于控制器对您的仓库进行单元测试。如果您现在被控制器中的repo引用所冒犯,那么就使用服务层。这完全是松耦合的。

服务层的好处包括完全隐藏数据访问机制,通过其他传输选项(例如Web服务)远程公开服务方法,以及使用API​​友好名称掩盖通用存储库方法。例如,post = MyAwesomeAPI.PostService.Get(id);可能只是泛型的包装器 - 通过id获取任何类型 - Repository.Get(id);在为第三方消费或开发团队中的其他开发人员开发一组服务时,此API包装非常有用。如果您的方法签名保持不变,您可以随时更改底层实现 - 例如,从NH切换到纯SQL不会破坏使用该API的现有应用程序。

为了获得最大的灵活性,您根本不会将服务程序集链接到repo实现程序集。相反,您将使用依赖注入工具(如Structure Map)在运行时连接所有内容。这允许您通过配置单独切换repo实现,而无需重新编译/链接。您甚至可以拥有多种数据访问技术。 API的消费者不会知道,也不应该关心。

如果您不需要任何这些东西,请在控制器中输入'using nhibernate'并完成。风险在于您已将MVC应用程序紧密绑定到NH,并且每个人都需要知道所做的一切,才能对您的应用进行最小的更改。该决定很可能是由您的项目限制(时间/金钱/人/日历)决定的。如果您确实需要所有这些东西,请查看Sharp架构,或组装您自己的堆栈。 MVC比M更多VC。

相关问题