问题描述
|
从内到外,这些是我们的MVC应用程序层:
MS sql /表/视图/存储的过程
具有POCO生成的实体框架4.1(ORM)
资料库
服务(检索)和控制功能(保存)
路由->控制器->剃刀视图
(客户端)带有Knockout.js(MVVM)的JQuery Ajax
一切都很好,直到我需要为第5步创建一个viewmodel来同时提供Razor视图和JSON / Knockout viewmodel:
包含所有下拉列表选项和以下字段的选择的标题
Items-我们发送给客户端的所有元素的数组,该数组成为viewmodel
由于Controller无法直接访问存储库,这是否意味着我为每个允许编辑内容的视图创建了服务?我需要从存储库中获取POCO,并根据需要获取每种字段类型的所有选项。
为每个视图创建单独的服务似乎很多余。例如,用于编辑地址的viewmodel和用于编辑也具有地址的房地产属性的单独viewmodel。我们可以有十几个表单来编辑相同的地址POCO。
为了使这个问题更容易回答,是否允许Controller直接访问存储库是一种泄漏的抽象?
解决方法
好吧,您的控制器是否将具有将POCO从Entity Framework转换为单独的视图模型对象的代码?
如果是这样,那么您应该将该代码移到一个单独的类,并遵循单一职责原则。该类是否在“服务层”中取决于您。而是否使用AutoMapper取决于您。但是,这类数据映射器不应成为控制器逻辑的一部分。控制器应该尽可能的笨。
好的,现在让我们忽略数据映射问题,并假设您始终可以将POCO直接用作视图模型。然后,您仍然需要一个服务层,因为它将在
userService.GetByUserName(\"bob\")
在您的哑控制器中,并通过返回特定的方式来实现
userRepository.Users.Single(u => u.UserName == \"bob\")
将它们放在一起,您的UserController
最终会获得IUserService
和IUserDataMapper
依赖性,并且代码是超级哑巴,如您所愿:
public ActionResult ShowUserPage(string userName)
{
var user = userService.GetByUserName(userName);
var viewModel = userDataMapper.MakeViewModel(user);
return View(viewModel);
}
现在,您可以使用存根测试这两个依赖项,或者在模拟IUserService
时存根out4ѭ,反之亦然。您的控制器几乎没有逻辑,并且只有一个变化轴。对于用户数据映射器类和用户服务类可以说相同。
今天早上我在阅读一篇文章,您可能会发现一些关于这些建筑问题的启发。在某种程度上,它的标题为“软件开发基础,第2部分:分层体系结构”。您可能无法从数据库应用程序模型切换到本文描述和建议的对持久性无知的模型。但这可能会为您指明正确的方向。
, 我个人总是将存储库注入到控制器中。我不确定为什么要在存储库和控制器之间建立服务层。如果有的话,您将使用规格。
完成此操作后,请查看自动映射器。它是一个映射器,一旦正确配置,它就可以将您的域模型映射到您的视图模型,然后再次映射。