这与这个问题有关:
What to put in Business Logic Layer?
有了这个问题的答案(还没有选择答案,因为可能会有其他人愿意发表评论以使我更清楚),我得出的结论是 BLL 将包含 CRUD 并将访问 DAL 作为需要。
我现在的主要问题是我的 BLL 是什么样子的?例如,一个 Order 对象。对于 CRUD,我看到一些具有 OrderService 的实现,它是 BLL 的一部分,如下所示:
public class OrderService
{
public int CreateOrder(Order order)
{
...
}
public int UpdateOrder(Order order)
{
...
}
//... other code for CRUD
}
除了业务对象之外,我在 BLL 中有与业务对象相关的服务吗?
而在其他一些他们做这样的事情:
public class Order
{
public int ID { get; set; }
public decimal Amount { get; set; }
//... etc.
public int Create()
{
...
}
public int Update()
{
...
}
}
但这似乎有点不对(结合 CRUD 操作和属性)。
BLL(CRUD 和业务对象)通常是如何构建的?
此外,由于数据通常来自 UI 输入然后填充到业务对象,我将如何验证数据?例如,我有订单和列表的总计属性,总计应等于 OrderItem 的总量。当说 CreateOrder 时,我将如何调用验证?我一直认为验证应该在实际的属性 setter 中完成。我将如何在 CRUD 期间调用它?我是否也应该在 Business Object 中实现 Validate 方法?
我们非常欢迎对此提出任何意见。
根据我的经验,我宁愿使用第一个。如果有更复杂的业务逻辑,那肯定是。通常我在复杂应用程序中有以下层:
- 查看。Razor 页面
- 型号。型号是Data Transfer Objects表示要显示 的内容,而不是来自数据库 的内容。
- Controller 。 Controller 可以是light-weight ,仅连接表示和业务逻辑。
- 业务逻辑。我更喜欢将 BL 放入单独的库 (BLL) 中。业务逻辑与 MVC Controller (通过 DTO)和数据层通信。
- 数据层。通过 EF 操作。
可以从多个数据库对象创建 DTO;如果您想隐藏一些细节,它们也可以是部分表示。阅读更多 in this question . DTO 也是一种强制自己预防的好方法 unintended updates -- 或参见 here .
在 Controller 可以做任何事情的小型应用中不需要 BLL。但在拥有各种服务和方面的大型应用程序中,您应该使用它。有人会说 BLL 是模型的一部分——好吧,有点是,但它不仅仅是填充 View 的东西。
让我再次强调:不要用大炮射麻雀……简单的任务需要简单的解决方案。
附加功能
您可以通过选择器表达式将 DB 实体映射到 DTO 实体。一个例子是 here , 我在下面放了另一个假设有一个 Kitten
数据库中的表。
Class KittenDto {
public static Expression<Func<Db.Kitten, KittenDto>> = (kitten) => return new KittenDto() {
Id = Id,
Name = Name,
CustomDataNotInDb = 42
};
public int Id;
public string Name;
public int CustomDataNotInDb;
}
然后你可以使用:
var kittenDto = context.Kittens
.Single(k => k.Id == givenId)
.Select(KittenDto.Selector);
注意,如果 Selector
不是 Expression<>
然后在本地执行。如果它是 Expression
然后它被转换成一个查询,数据库完成剩下的工作。数据库的结果将是 KittenDto
对象(或更准确地说:它将仅具有请求的属性,仅此而已)。
另请注意,编写复杂的表达式可能很困难——或者我上次在 .NET 4.5 周围使用它时就是这样。例如函数调用不能在数据库查询中执行,只能在一些非常常见的查询中执行(比如一些字符串操作)。