【问题标题】:Service layer and project structure in ASP.NET MVC 5 without repository and UoW patternsASP.NET MVC 5 中的服务层和项目结构,没有存储库和 UoW 模式
【发布时间】:2014-11-05 19:03:00
【问题描述】:

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

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

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

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

数据层:我读过很多关于 Repository 和 UoW 模式的文章。有一些文章表明 EF6 实现了这两件事。如果不需要这种行为,我不想创建额外的代码。问题是:我认为我不需要它们是否正确?

这是我的流程:

ViewControllers(使用 ViewModels)Services(使用 Models)DB。

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

你觉得我的项目结构怎么样?

【问题讨论】:

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


    【解决方案1】:

    如果您不需要创建通用数据访问机制,则没有理由将工作单元模式与实体框架一起使用。只有在以下情况下,您才会这样做:

    1. 使用本身不支持工作单元模式(EF 支持)的数据访问技术
    2. 希望能够在未来某个时候更换数据提供者。但是,这并不像看起来那么容易,因为即使在使用工作单元时也很难不引入对特定数据技术的依赖(也许甚至因为你是)...或
    3. 您需要有一种方法将不同的数据源统一到一个原子事务中。

    如果这些都不是,您很可能不需要自定义工作单元。另一方面,存储库可能很有用......但是使用 EF6 也可以使用存储库的许多好处,因为 EF6 提供了用于测试的模拟接口。无论如何,请远离通用存储库,除非它只是具体存储库的实现细节。将通用存储库暴露给您的其他层是一个巨大的抽象泄漏......

    我总是使用存储库/服务/外观模式来创建我的数据和业务(以及 UI 和业务)层之间的分离。它提供了一种方便的模拟方式,而无需模拟您的数据访问本身,并将您的逻辑与 EF 使用的 Linq 层引入的特定逻辑解耦(Linq 相对通用,但有些东西是 EF 特有的),外观/存储库/服务器接口将其解耦)。

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

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

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

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

    【讨论】:

    • 谢谢埃里克。我明白你的意思。你提到了验证——我明白你的意思。在您的项目中,Repository 和 Façade 到底是什么?
    • @WaltLift0 - 存储库模式实际上只是一种专门的外观模式。它把你真正的实现放在一个接口后面来分离它,所以双方都不知道对方。
    【解决方案2】:

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

    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 为后缀,以帮助人们(程序员)区分所有其他类(包括视图模型)。

    在我最近参与的一个项目中,团队并没有完全理解这个概念,因此他们不会将他们的 Views 强类型化为 Models,而是将其视图强类型化为 DTO classes。理论上和实践中一切正常,但他们很快发现他们的 DTO 中有 IsVisible 等属性,而事实上;这些属性应该属于您的 ViewModel 类,因为它们用于 UI 逻辑。

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

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

    您的Service Layer 不应该有ViewModel 的概念。它应该只接受、接收、发送等... POCO 类。

    这意味着从您的Controller,在您的ActionResult 中,一旦ModelStateValid,您需要将您的ViewModel 转换为POCO,然后将其发送到里面的方法你的Service Layer

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

    这样,您的AddNewPerson() 方法将接收Person 对象作为其参数,而不是接收PersonViewModel 参数。

    请记住,这仅适用于 if and only if 您的 Service Layer 为其他事情提供服务的计划...

    如果不是这样,请随时让您的Service Layer 接收、发送、添加等...ViewModels 而不是 POCO。这取决于您和您的团队。

    请记住,给猫剥皮的方法有很多种。

    希望这会有所帮助。

    【讨论】:

    • 不正确。 ViewModel 的概念是由 Martin Fowler 创建的,尽管他将其称为“演示模型”,并且在他的演示模型模式中进行了定义。请参阅martinfowler.com/eaaDev/PresentationModel.html - 顺便说一下,它称为 NuGet,而不是 nugget。我之所以提到它,是因为您似乎对命名法如此执着。
    • 正确,我使用的法语版 Word 忽略了这个错误。感谢您的更正:-)
    • 谢谢你。你让我明白了一些问题。回到 Model 和 ViewModel 之间的差异。我认为他们在模仿一些不同的东西:模型 - 业务对象,ViewModel - 从业务对象中选择的项目 + 为最终用户提供一些额外的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2010-11-23
    • 2019-09-04
    • 2017-09-19
    • 1970-01-01
    • 2020-06-02
    • 2016-10-07
    相关资源
    最近更新 更多