在ASP.NET MVC项目中实现数据库Repository时,将业务逻辑放入其中是正确的吗?还是将逻辑放入控制器类中更好?或者使用其他服务和辅助类来操作数据?
在ASP.NET MVC项目中实现数据库Repository时,将业务逻辑放入其中是正确的吗?还是将逻辑放入控制器类中更好?或者使用其他服务和辅助类来操作数据?
在业务逻辑方面,最好的选择是将其置于自己的层中(作为“模型”层的一部分),没有什么地方是完美的。虽然有时可以使用不同的实现方式,但在每种情况下都存在权衡。
创建用于业务逻辑的另一层代价在于你必须要真正封装你的代码。如果你过于激进,也可能会在实体和域模型之间产生重复(如果您的数据库关系语义已经处理了您的业务逻辑)。
视图
视图是应用程序最容易发生变化的部分,因此也是最脆弱的部分。
由于需要支持所有各种视图状态转换,因此在视图中正确处理业务逻辑非常困难。
现在人们都知道这样做是极不可取的 :)
存储库
这里的问题在于维护和抽象的纯洁性。违反这一点可能会使人们感到困惑,并使您的应用程序难以维护。
存储库充当域和数据映射层之间的中介,就像一个内存中的域对象集合。
存储库是一种将您的数据存储呈现为持有域对象的集合的抽象。
其中不应该包含任何领域逻辑。相反,它应该存在于您的领域对象中(按定义,因为您的业务逻辑就是您的领域)。
否则(使您的存储库具有双重功能并验证域逻辑)将违反SRP(单一责任原则),并且可能会产生代码异味。
您可以拥有更高级别的领域对象来处理领域对象集合(例如对象集合内的依赖关系、大小限制等)以验证领域逻辑。它们仍将在底层使用您的存储库来执行域对象的最终存储/检索,因此它们不会承担双重职责(因此也不违反 SRP)。
控制器
控制器也不是放置业务逻辑的好地方。控制器的工作是在控制器和模型之间进行协调。
模型是领域,领域便是你的业务逻辑。
实体
你可以考虑将领域数据放在实体中。
但是,如果实体已经连接,则访问导航属性时必须小心,因为这可能会触发意外的数据库查询或异常(取决于上下文是否被释放)。解除它们的连接也是一个问题,因为除非你在从上下文分离它们后显式重新连接对象到彼此,否则会破坏你的对象图。
如果你创建单独的领域模型类,你可以将实体视为仅限于DTOs。
编辑:IValidatableObject
我刚刚了解到 Entity Framework 4.1 中的一个功能,你可能想要检查一下:接口IValidatableObject
。
你可以将你的实体类设置为 partial 类,在 partial 类中实现该接口。这样,当你保存时,Entity Framework 将调用Validate
方法,你也可以在适当的时候调用Validate
方法。
这可能有助于你在其他情况下避免将持久化模型与领域模型分开。
请参阅此文章:http://msdn.microsoft.com/en-us/data/gg193959
附注:视图/视图模型
如果你考虑这个问题,我建议你避免将实体传回视图。它会在许多情况下出现错误(例如Javascript序列化以存储视图状态),并且在其他情况下会导致意外的数据库查询。相反,应该传回简单类型(如字符串、整数、列表、哈希集合、字典等),或者构造视图模型类以传递给视图。
我同意上述观点,控制器不应该负责业务逻辑,只需返回适当的视图。我使用服务层提供业务逻辑和视图模型创建,以便控制器仅将从服务返回的模型传递给视图。
我还确保我的视图模型是简单的DTO,并且服务只需知道如何适当地填充属性即可。
IValidatableObject
接口。这并不能完全解决所有问题,但在某些情况下可以帮助你避免将领域模型与持久化模型分离。 - Merlyn Morgan-Graham