使用存储库时,ASP.NET MVC中业务逻辑的最佳位置是什么?

Ale*_*der 14 .net c# asp.net asp.net-mvc design-patterns

在ASP.NET MVC项目中为数据库实现Repository时,将业务逻辑放入其中是否正确,或者将逻辑放在控制器类中可能更好?或者使用其他服务和帮助程序类来操作数据?

Mer*_*ham 14

最终,除了自己的层(作为"模型"层的一部分)之外,您的业务逻辑还没有一个完美的位置.通常情况下,您可以使用不同的实现方式,但在每种情况下都需要权衡利弊.

为业务逻辑创建另一层的权衡是您必须实际封装代码.如果你过于咄咄逼人,你的实体和域模型之间也可能会出现一些重复(如果你的数据库的关系语义已经处理了你的buiness逻辑).

视图

视图是应用程序中最脆弱的部分,因为它最有可能发生变化.

由于必须支持所有各种视图状态转换,因此在视图中获取业务逻辑也非常困难.

现在众所周知,你只是不这样做:)

知识库

这里的问题是维护和抽象的纯粹之一.违反此规定会让人感到困惑并使您的应用难以维护.

来自EAA关于存储库模式的文章:

存储库在域和数据映射层之间进行调解,其作用类似于内存中的域对象集合

存储库是一种抽象,它将您的数据存储呈现为包含域对象的集合.

没有域逻辑应该驻留在其中.相反,它应该存在于您的域对象中(根据定义,因为您的业务逻辑您的域).

否则(使您的存储库执行双重任务并验证域逻辑)将违反SRP(单一责任原则),并且会产生代码异味.

您可以使用更高级别的域对象来处理域对象集合,以验证域逻辑(例如对象集合中的依赖关系,大小限制等).他们仍将使用您的存储库来进行域对象的最终存储/检索,因此他们不会执行双重任务(因此不会违反SRP).

调节器

控制器也不是放置业务逻辑的好地方.控制器的工作是在控制器和模型之间进行调解.

模型是域,域是您的业务逻辑.

实体

您可以考虑将域数据放入实体中.

但是,如果附加了实体,则在访问导航属性时必须小心,因为您可能会触发无意的数据库查询或异常(取决于您的上下文是否被处置).分离它们也是一个问题,因为它会破坏您的对象图,除非您在将对象从上下文中分离后明确地重新附加对象.

如果您创建单独的域模型类,则可以考虑仅将实体视为DTO.

编辑:IValidatableObject

我刚刚发现了您可能想要查看的实体框架4.1中的一个功能:IValidatableObject界面.

您可以使实体成为部分类,并在部分类中实现此接口.当你这样做时,实体框架会调用Validatesave,你可以Validate在有意义的时候调用它.

这可以帮助您避免在其他情况下将持久性模型与域模型分开.

请参阅此文章:http://msdn.microsoft.com/en-us/data/gg193959

附注:视图/视图模型

如果您正在考虑它,我建议您避免将实体传递回视图的诱惑.它会在很多情况下中断(例如,Javascript序列化以存储视图状态),并在其他情况下导致无意的数据库查询.传递简单类型(字符串,整数,列表,哈希集,字典等),或构造视图模型类以传递给视图.


Pra*_*nth 6

添加服务层以将模型传递到Repository,其中可以添加与控制器对应的Service类.例如,如果使用UserController和User Model,则可以将User Model传递给UserService类.

这里,服务层可以充当存储库和控制器之间的桥梁,以便很好地建立Controller和存储库的分离.


Ami*_*abh 5

业务逻辑应该存在于您的域模型中.

请看看这个答案.

ASP.NET MVC - 控制器中是否应存在业务逻辑?