ASP.NET MVC 5中的服务层和项目结构,没有存储库和UoW模式

时间:2014-09-11 17:55:26

标签: asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6 service-layer

我想使用EF 6 Code第一概念在ASP.NET MVC 5中创建一个好的应用程序。我希望它设计得很好,即一般来说:表示,逻辑和数据层是分开的。我希望它可以测试:)

这是我的想法以及与创建应用程序相关的一些问题

表示层:这是我的整个MVC - 视图模型(不是模型),视图,控制器 我认为验证应该在其他地方完成(在我看来 - 它是业务逻辑的一部分)但是在ViewModelds中使用DataAnnotations命名空间中的属性并在控制器中检查验证是非常方便的。

逻辑层:服务 - 具有规则业务逻辑接口的类。 我把那些函数放在:AddNewPerson(PersonViewModel Person),SendMessageToPerson(...)。 他们将使用数据库上下文来进行操作(有可能并非所有人都依赖于上下文)。服务和db之间有直接连接 - 我的意思是服务类有引用做上下文。 我应该在ViewModel和Model之间进行映射?我听说服务对它来说是一个不好的地方 - 所以也许在控制器中。我听说服务应该专门做与db相关的工作。 这样对吗?我的服务层图片好吗?

数据层:我已经详细了解了Repository和UoW模式。有一些文章表明EF6实现了这两件事。如果不需要这样的行为,我不想创建额外的代码。问题是:我是否认为我不需要它们?

这是我的流程:

查看< - >控制器(使用ViewModels)< - >服务(使用模型)< - > DB。

**我将在我的项目中使用DI。

您如何看待我的项目结构?

2 个答案:

答案 0 :(得分:3)

如果您不需要创建通用数据访问机制,则没有理由在Entity Framework中使用工作单元模式。你只会这样做:

  1. 使用本身不支持工作单元模式的数据访问技术(EF确实如此)
  2. 希望能够在未来的某个时间交换数据提供商..但是,这并不像看起来那么容易,因为即使使用工作单元也很难不引入特定数据技术的依赖性(也许甚至因为你是......或
  3. 您需要有一种方法可以将不同的数据源统一到原子事务中。
  4. 如果不是这种情况,您很可能不需要自定义工作单元。另一方面,存储库可能很有用......但是使用EF6还可以获得存储库的许多好处,因为EF6提供了用于测试的模拟接口。无论如何,请远离通用存储库,除非它只是您具体存储库的实现细节。将通用存储库暴露给其他层是一个巨大的抽象泄漏...

    我总是使用Repository / Service /Façade模式来创建数据和业务(以及UI和业务)层之间的分离。它提供了一种方便的模拟方法,无需模拟您的数据访问本身,它将您的逻辑与EF使用的Linq层引入的特定内容分离(Linq相对通用,但有些内容特定于EF), façade/ repository / server接口解耦了。)。

    一般来说,你走在正确的道路上......但是,我要指出在视图模型上使用数据属性是一件好事。这会将您的验证集中在您的模型上,而不是让您将验证逻辑放在一起。

    您在业务逻辑中也需要验证,这是正确的,但您的错误是假设您应该只在业务逻辑上使用它。您需要在应用程序的所有层进行验证。特别是,您的UI验证可能具有与业务逻辑验证不同的要求。

    例如,您可以在UI中实施创建新帐户作为多步骤向导,这需要与业务层进行不同的验证,因为每个步骤仅包含总对象验证的子集。或者您可能要求您的移动界面具有与您的网站不同的验证要求(一个可能使用验证码,而另一个可能使用基于触摸的人工验证)。

    无论哪种方式,重要的是要记住验证在客户端,服务器和各个层都很重要......

答案 1 :(得分:1)

好的,让我们澄清一些事情......

ViewModel的概念(或ViewModel的实际措辞)是由 Microsoft Martin Fowler引入的。事实上,ViewModel只不过是一个简单的class

实际上,您的Views被强类型为classes。期。为避免混淆,提出了ViewModel措辞来帮助人们理解

  

“此类,将由您的视图使用”

因此我们称之为ViewModel

此外,虽然许多书籍,文章和示例都使用ViewModel这个词,但我们不要忘记它只不过是Model

事实上,你有没有注意到为什么MVC应用程序中有Models文件夹而不是ViewModels文件夹?

此外,您是否注意到在视图的顶部有@model指令而不是@ viewmodel指令?

那是因为一切都可以成为模特。

顺便说一下,为了清楚起见,我们非常欢迎您删除(或重命名)Models文件夹并创建一个名为ViewModels的新文件夹(如果有帮助的话)。

无论您做什么,最终都会在页面顶部调用@model而不是@viewmodel

另一个类似的例子是DTO classes。 DTO类只不过是常规类,但它们后缀为DTO,以帮助人(程序员)区分所有其他类(包括View模型)。

在我最近开展的一个项目中,团队没有完全掌握这个概念,所以他们的Views强烈输入Models,而不是强烈输入DTO classesIsVisible。在理论和实践中,一切都在发挥作用,但他们很快发现,事实上他们在DTO中有ViewModel等属性;这些属性应属于您的Service Layer类,因为它们用于UI逻辑。

到目前为止,我还没有回答你的问题,但我确实有关于快速架构的类似帖子。您可以阅读帖子here

我想指出的另一件事是,当且仅当您的Service Layer计划为其他事项提供服务时,例如Winform应用程序,移动网站等...然后ViewModels不应该收到Service Layer

您的ViewModel不应该知道什么是Controller。它应该只接受,接收,发送等...... POCO课程。

这意味着,ActionResultModelStateValid ViewModel Service Layer后,您需要将Automapper转换为POCO反过来,将被发送到ViewModel

中的方法

换句话说,我使用/安装AddNewPerson() nugget包并创建一些扩展方法,将Person转换为POCO,反之亦然(POCO转换为ViewModel)。 / p>

这样,您的PersonViewModel方法会为其参数收到if and only if个对象,而不是接收Service Layer参数。

请注意,这只是Service Layer您的ViewModels有效服务其他事项的计划......

如果情况并非如此,请随时让{{1}}接收,发送,添加等... {{1}}代替POCO。这取决于您和您的团队。

请记住,有许多方法可以给猫皮肤。

希望这有帮助。