系统有一个页面,用户可以通过指定开始日期和结束日期来搜索项目。这些是普通日期(没有时间成分)。对于用户来说,包含结束日期似乎是最直观的(因此也包括该结束日期的所有项)。
但是,项的CreateDate在数据存储中确实包含时间组件。实际上,这意味着我们需要将这个永恒的结束日期转换为第二天的0:00:00小时日期。这样我们可以编写以下查询:

SELECT *
FROM   Items
WHERE  CreateDate >= @STARTDATE
AND    CreateDate < @ENDDATE

转换此结束日期与编写这行代码一样简单:
endDate.Date.AddDays(1);

我的问题是:
我应该考虑这最后一行代码业务逻辑,它应该放在业务层,还是应该考虑这一行是一个“模型绑定逻辑”,它应该放在表示层?
当它被放置在bl中时,这意味着bl知道表示层,因为提供值的方式是特定于接口的。另一方面,由于操作在业务层定义为DTO,我还可以将此对象视为接口,这对表示层来说应该很方便。
这个问题在本质上可能是哲学性的,因为可能有多种方法来看待这个问题,而实际的转换代码是微不足道的。我很想知道你为什么认为它应该放在一层而不是另一层。
我不认为应用程序的体系结构会对这个问题的答案产生任何影响。但是为了更完整地描述这个架构,它基于commandsqueries并且表示层创建了一个由业务层处理的查询对象。pl代码通常如下所示:
public Action Filter(DateTime start, DateTime end)
{
    var query = new GetItemsByStartEndEndDateQuery
    {
        StartDate = start.Date,
        EndDate = end.Date.AddDays(1)
    }

    var items = this.queryProcessor.Handle(query);

    return this.View(items);
}

或者在可能的情况下,(mvc)模型绑定用于简单地对命令和查询对象进行模型绑定(这非常方便):
public Action Filter(GetItemsByStartEndEndDateQuery query)
{
    var items = this.queryProcessor.Handle(query);

    return this.View(items);
}

当有多个用户参与(例如,wcf层和mvc层)时,您的答案会改变吗?

最佳答案

对于业务层公开的服务语义,应该有一个契约,并且可能有该契约的自动化测试。
此合同应定义如何解释和验证输入参数,例如:
如果startdate>enddate,结果如何?
可接受的日期范围是什么(例如,对于SQL Server,早于1/1/1753的日期是什么情况)?
是否允许输入参数具有非零的日时组件,如果是,则如何处理日时(仅截断并使用日期;如果调用方包含日时组件,则引发异常;或者允许调用方指定包含日时组件的范围)。
范围是独占的还是包含的?
如何处理时区(例如,kind=local、utc或unspecified的日期参数)?
如果这个契约与表示层想要从用户那里获取输入的方式不匹配,那么表示层可以进行映射以匹配契约。
当然,如果契约与数据访问层期望的日期范围不匹配,业务层可以映射到数据访问层期望的任何内容。

09-30 17:29
查看更多