【发布时间】:2011-12-08 07:57:15
【问题描述】:
在 ASP.NET MVC 项目中为数据库实现 Repository 时,将业务逻辑放入其中是否正确,或者将逻辑放入控制器类中是否更好?或者使用额外的服务和帮助类来操作数据?
【问题讨论】:
标签: c# .net asp.net asp.net-mvc design-patterns
在 ASP.NET MVC 项目中为数据库实现 Repository 时,将业务逻辑放入其中是否正确,或者将逻辑放入控制器类中是否更好?或者使用额外的服务和帮助类来操作数据?
【问题讨论】:
标签: c# .net asp.net asp.net-mvc design-patterns
除了它自己的层(作为“模型”层的一部分)之外,您的业务逻辑最终没有一个完美的地方。通常您可以采用不同的实现方式,但在每种情况下都需要权衡取舍。
为业务逻辑创建另一个层的权衡是您必须实际封装您的代码。如果您过于激进,您的实体和域模型之间可能还会出现一些重复(如果您的数据库的关系语义已经处理了您的业务逻辑)。
查看
视图是应用中最脆弱的部分,因为它最有可能发生变化。
由于必须支持所有各种视图状态转换,因此在您的视图中获得正确的业务逻辑也非常困难。
众所周知,现在你只是不这样做 :)
存储库
这里的问题是抽象的维护和纯度之一。违反此规定会使人们感到困惑并使您的应用难以维护。
来自the P of EAA article on the Repository pattern:
存储库在域和数据映射层之间进行中介,就像内存中的域对象集合一样
存储库是一种抽象,它将您的数据存储呈现为一个集合,包含域对象。
没有域逻辑应该驻留在其中。相反,它应该存在于您的域对象中(根据定义,因为您的业务逻辑是您的域)。
否则(让您的存储库执行双重职责并验证域逻辑)将违反 SRP (Single Responsibility Principle),并且会产生代码异味。
您可以让更高级别的域对象与域对象的集合一起工作以验证域逻辑(例如对象集合中的依赖关系、大小限制等)。他们仍将在幕后使用您的存储库来进行域对象的最终存储/检索,因此他们不会承担双重职责(因此不会违反 SRP)。
控制器
控制器也不是放置业务逻辑的好地方。控制器的工作是在控制器和模型之间进行调解。
模型就是领域,领域就是你的业务逻辑。
实体
您可以考虑将域数据放入实体中。
但是,如果附加了实体,则在访问导航属性时必须小心,因为您可能会触发无意的数据库查询或异常(取决于您的上下文是否已释放)。分离它们也是一个问题,因为它会破坏您的对象图,除非您在将对象从上下文中分离后明确地将它们重新附加到彼此。
如果您创建单独的域模型类,您可能会考虑仅将实体视为DTOs。
编辑:IValidatableObject
我刚刚发现了 Entity Framework 4.1 中的一个功能,您可能想了解一下:IValidatableObject 接口。
您可以使您的实体成为分部类,并在分部类中实现此接口。当您这样做时,Entity Framework 将在保存时调用 Validate,并且您可以在需要时调用 Validate。
这可能有助于避免在其他情况下将持久性模型与域模型分开。
见这篇文章:http://msdn.microsoft.com/en-us/data/gg193959
旁注:视图/视图模型
如果您正在考虑它,我建议您避免将实体传递回视图的诱惑。它会在很多情况下中断(例如 Javascript 序列化以存储视图状态),并在其他情况下导致无意的 DB 查询。而是传回简单类型(字符串、整数、列表、哈希集、字典等),或者构造视图模型类以传递给视图。
【讨论】:
IValidatableObject 界面所做的编辑(靠近底部)。它不会完全解决任何这些问题,但会帮助您避免在某些情况下将域模型与持久性模型分开。
添加一个Service Layer,将模型传递给Repository,其中可以添加控制器对应的Service类。例如,如果您使用 UserController 和 User Model,您可以将 User Model 传递给 UserService 类。
在这里,Service Layer 可以充当 Repository 和控制器之间的桥梁,从而很好地建立了 Controller 和 Repository 的分离。
【讨论】:
【讨论】:
我同意上述观点,控制器不应该仅仅为返回适当的视图而负责业务逻辑。我使用服务层来提供业务逻辑和视图模型创建,以便控制器简单地将服务返回的模型传递给视图。
我还确保我的视图模型是简单的 DTO,并且服务只知道如何适当地填充属性。
【讨论】:
在我看来,这取决于业务逻辑。是否基于输入和输入规则验证的逻辑,如果是这样,最好放在模型上。但是,如果它是基于工作流的业务规则,那么可能需要在控制器中,例如,用户选择选项 A 然后被重定向到与选择选项 B 不同的页面/表单。如果业务规则必须处理数据持久性,那么它可能需要进入存储库(将它放在那里对我来说似乎很奇怪)。对此进行了大量讨论,但这取决于您或您的团队对最终产品的可维护性和灵活性的看法。
【讨论】: