数据访问层中的计算

时间:2014-01-11 15:24:41

标签: c# data-access-layer n-tier-architecture separation-of-concerns bll

我正在使用n层方法将大型Classic ASP Web应用程序转换为ASP.Net MVC。在我的DAL中,我使用ADO.Net来查询数据库并将查询转换为对象。我也有BLL用于计算和验证等事情。

我的问题是在需要进行计算时将DAL执行计算,以便将查询转换为对象。举一个例子,考虑一个包含摘要信息和订单项的发票系统:

public class Invoice
{
    public int InvoiceID { get; set; }
    public DateTime InvoiceDate { get; set; }
    public decimal InvoiceTotal { get; set; }
    public List<InvoiceLineItem> LineItemList { get; set; }
}

因此,我在数据库查询中转换订单项的代码如下所示:

decimal InvoiceTotal = 0;
var LineItem = new InvoiceLineItem();
while (Reader.Read())
{
    LineItem.ItemID = Extensions.SafeGetInt(Reader, "ItemID");
    LineItem.Price = Extensions.SafeGetDecimal(Reader, "Price");
    LineItem.Quantity = Extensions.SafeGetInt(Reader, "Quantity");
    LineItemList.Add(LineItem);

    InvoiceTotal = InvoiceTotal + (LineItem.Price * LineItem.Quantity);    
}

Invoice.InvoiceTotal = InvoiceTotal;
etc ...

所以这是我的问题:考虑到我的n层体系结构,我的DAL是执行InvoiceTotal计算的正确位置吗?考虑到BBL的部分工作是执行计算,这是否违反了DAL和BLL之间的关注点分离?或者我是否采用BBL的字面意义执行计算的功能,如果需要这些计算来填充模型,那么在DAL中进行计算是否可行?我发现在DAL中进行InvoiceTotal计算很有吸引力的一个原因是因为我只需要在发票项目记录上迭代一次。如果我在其他地方创建了一个单独的InvoiceTotal函数来获取InvoiceTotal,那么我将不得不第二次迭代记录。

编辑:事实证明,真正的问题不在于是否应该在DAL中允许计算,而是InvoiceTotal是否应该在我的模型中。从数据库规范化角度来看,它不是必需的,因为总计可以从订单项计算。在这种情况下,InvoiceTotal不应该在我的模型中,但应该在我的ViewModel中,在这种情况下,不需要在我的DAL中进行计算。我可以出于性能原因忽略数据库规范化问题,并在我的模型中包含InvoiceTotal,但如果是这种情况,我会将InvoiceTotal持久保存到数据库中,在这种情况下填充我的模型时不需要进行任何计算,因为我只需从中提取值数据库。

经验教训:如果我想在我的DAL中进行计算,我的模型可能存在缺陷。

1 个答案:

答案 0 :(得分:3)

我会将计算添加到业务逻辑层

发票总额的初始计算应该在您将其写入数据库之前在应用程序中提供,这样您就不会想要在检索记录时计算总数的唯一位置。

将其添加到业务逻辑层的另一个好理由是它可以从DAL返回的行数据派生,这将使DAL层专注于写入和读取数据。这也可以将您的计算保存在一个地方。

但是,由于发票总额在发送后已修复,您可能需要在首次保存时写入初始值,然后允许手动修改。在这种情况下,发票总计算将在业务层中完成,但该值也将写入数据库并从数据库中检索而不进行重新计算。