我对BLL和DAL的关系有点困惑。 BLL是否应通过依赖注入封装DAL?或者BLL是否只对域对象和DAL单独保存/更新?
例如想象(在典型的MVC应用程序中)取消订单功能,要求您更新订单并更新库存。以下是我的行动的样子吗?
public ActionResult CancelOrder (Guid orderId) {
Order order = orderRepository.Get(orderId);
StockItem stockItem = stockRepository.Get(order.StockItemId);
_orderService.CancelOrder(order, stockItem);
orderRepository.Update(order);
orderRepository.Update(stock);
Return View();
}
或者它应该更像是以下内容?
public ActionResult CancelOrder (Guid orderId) {
_orderService.CancelOrder(orderId);
Return View();
}
(within OrderService)
public void CancelOrder(Guid orderId) {
Order order = orderRepository.Get(orderId);
StockItem stockItem = stockRepository.Get(order.StockItemId);
order.Cancelled = true;
stockItem.AmountInStock = stockItem.AmountInStock + order.Amount;
orderRepository.Update(order);
orderRepository.Update(stock);
}
使用此选项,BLL将处理所有内容,包括数据访问。将注入存储库以避免紧密耦合。然后,任何实体检索都将采用_orderService.GetOrder(orderId);
的形式,直接进入存储库。
请原谅示例的粗糙,因为我没有太多时间。我在远处写的任何东西是否有意义,或者我是否在荒野中离开?
答案 0 :(得分:5)
绝对不是第一个将业务逻辑嵌入控制器的选项。问题不在于控制器本身访问数据对象,而是必须遵循业务规则规定的过程。此过程在控制器中没有位置。
因此,您应该使用第二个选项,或者可以使Cancel
成为Order
的方法。如果您已经编写了类似的代码,那么请保持一致性。
答案 1 :(得分:1)
考虑到关注点分离,Controller来自MVC模式,即PRESENTATION模式,因此控制器应该包含表示逻辑支持表示层,而不是业务逻辑。
同意业务逻辑应该在域实体中,但是也有一些APPLICATION逻辑在存储库之间起协调作用,这就是服务层在路上被击落的原因。
因此,选项2应该是你的方式。
答案 2 :(得分:1)
你真的在这里提出两个问题:
Controller与业务层中的内容应该是什么?
=>我倾向于认为你的第一个代码段中的代码是应用程序层服务的正确级别(如果你承认这两者可以被比作,那么对于一个控制器,其中有很多关于这些时间的讨论) 。从存储库中获取Order
并在取消操作后保存它几乎不是纯粹的业务逻辑。它更多地与周围的事务/工作单元和用例的管道有关。
我只是改变一件事 - 尝试一次性保存对您的交易影响的所有实体的更改。如果您必须手动更新在操作结束时可能会更改的每个实体,那将会非常痛苦,并且会不必要地污染控制器。创建一个工作单元系统(或使用现有实现),它将立即保留所有更改并删除存储库中的所有Update()方法。
除此之外,正如Jon建议的那样,我也相信包含Order
方法的丰富的Cancel()
域对象更适合服务 - 但这是另一个争论。
BLL和DAL之间应该有什么样的关系?
=> BLL不应该与DAL紧密耦合,并且作为最中心层,它不应该直接引用外层。这样,您可以轻松地在另一个应用程序中使用另一个DAL等重用BLL。
但是,有些业务对象有时需要直接访问他们尚未引用的其他对象,这基本上意味着从数据库中获取它们。换句话说,BLL中的某些操作需要与存储库通信。因此,我总是将存储库 interfaces 放在BLL中,但是它们的实现驻留在DAL中,并且它们在运行时被注入BLL。
结果,BLL仅松散地耦合到DAL。它仍然是持久性无知,因为它只操纵外观(存储库),这些外观看起来像中性的对象集合,并且不会忘记数据的存储,保存等等。
答案 3 :(得分:0)
BLL应该对您为应用程序创建的业务对象执行操作。理想情况下,它不应该知道数据库和相关操作。如果您希望保持松散耦合,请使用依赖注入从DAL调用方法。