BLL(CRUD和业务对象)通常是如何构建的?

时间:2014-10-27 14:10:57

标签: c# asp.net-mvc n-tier-architecture

这与这个问题有关:

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
}

除了Business对象外,我还有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输入,然后填充到Business对象,我将如何验证数据?例如,我有订单和列表的属性总计,总计应该等于OrderItem的总金额。在说CreateOrder时,我将如何调用验证?我一直认为验证应该在实际的属性设置器中完成。如何在CRUD期间调用它?我是否应该在Business Object中实现Validate方法?

对此的任何意见都非常受欢迎。

1 个答案:

答案 0 :(得分:1)

根据我的经验,我宁愿使用第一个。如果有一个更复杂的业务逻辑,那么肯定。通常我在复杂应用程序中有以下图层:

  • 查看。 Razor页面
  • 模型。模型是Data Transfer Objects,代表显示的内容,而非来自数据库
  • 控制器。控制器可以是light-weight,只能连接演示文稿和业务逻辑。
  • 商业逻辑。我更喜欢将BL放入单独的库(BLL)。业务逻辑与MVC控制器(通过DTO)和数据层进行通信。
  • 数据层。通过EF操作。

可以从多个DB对象创建DTO;如果你想隐藏一些细节,它们也可以是部分表示。阅读更多in this question。 DTO也是强迫自己阻止unintended updates - 或查看here的好方法。

在控制器可以执行所有操作的较小应用程序中不需要BLL。但是在具有各种服务和方面的大型应用程序中,您应该使用它。有人会说BLL是模型的一部分 - 嗯,有些是,但它远远超过填充视图的东西。

让我再次强调:不要使用大炮射麻雀......简单的任务需要简单的解决方案。

ADD-ON

您可以通过选择器表达式将数据库实体映射到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,那么它将转换为查询,DB将完成其余的工作。数据库的结果将是一个KittenDto对象(或更确切地说:它只有所请求的属性,仅此而已)。

还要注意编写复杂的表达式可能很困难 - 或者是我上次在.NET 4.5中使用它时。例如,函数调用不能在DB查询中执行,只能执行一些非常常见的函数调用(如某些字符串操作)。