在n层c#应用程序中何处放置计算逻辑

本文关键字:何处放 计算逻辑 应用程序 | 更新日期: 2023-09-27 18:09:13

我正在用c#开发一个n层应用程序,使用下面的应用程序结构。

My Solution结构。

    UI - WPF Prism和ViewModels连接到服务。商店员工使用。
  1. Services - WCF - Business Logic, Data Retrieval and connection to DB through Data layer.
  2. 实体- EF POCO实体-无逻辑。
  3. 数据- EF DbContext和EDMX - DB连接
  4. Web - ASP。. NET MVC应用程序-基于UI的web版本,功能有限,客户访问权限有限。

我想知道在哪里有计算的实体对象的逻辑。

这是样本实体。

public class Invoice
{
    public int InvoiceID { get; set; }
    public DateTime InvoiceDate { get; set; }
    public Decimal SubTotal { get; set; }
    public Decimal? SalesTax { get; set; }
    public Decimal? DiscountPercent { get; set; }
    public Decimal? DiscountAmount { get; set; }
    public decimal Total { get; set; }
    public ICollection<InvoiceDetail> InvoiceDetails { get; set; }
}
public class InvoiceDetail
{
    public int InvoiceDetailID { get; set; }
    public int InvoiceID { get; set; }
    public Decimal Quantity { get; set; }
    public Decimal Price { get; set; }
    public decimal Total { get; set; }
    public Invoice Invoice { get; set; }
}

在上面的场景中,当值发生变化时,我应该将计算发票总额的逻辑放在哪里?例如,更新的SalesTax将需要更改Invoice Total。在发票中添加行项目需要更改小计、税、折扣和总额。

我想知道我是否可以在服务层做到这一点,让实体贫血。我担心的是,我需要不断地在网络上来回发送整个发票对象。

尽管我还没有做移动解决方案,但我不确定这在移动环境中是否是个好主意,因为来回发送发票可能会消耗数据。

另一个想法,例如,我认为是在InvoiceDetail中有AddLineItem()方法,在Invoice中有CalculateTotals()。

AddLineItem自动计算行项目的total(这可以使其成为DB中的计算列),并计算发票的小计、折扣、税和total。我假设在这种情况下,如果我想在内部调用CalculateTotals(),例如当SalesTax发生变化时,而不是让客户端调用CalculateChanges时,我可能必须删除自动属性。对吗?如果是,这对我来说是一个问题,重构EF模板,使其不具有自动属性,而是具有支持字段的属性。

请告知哪种方法更好,为什么?或者是完全不同的方法。谢谢你的帮助。

在n层c#应用程序中何处放置计算逻辑

在我们的工具中有一个类似的问题,并将计算放在Domain对象本身中。一个对象应该知道它的总数是因为它知道它的子对象。我们的服务层中使用的业务逻辑特定于业务规则,而不是计算。下面是我们的代码示例(注意:我们使用c#)。Net with MVC3):

public class Task : DomainBase
{
    public virtual ICollection<Subtask> Subtasks { get; set; }
    [Display(Name = "Subtask(s) Total Cost")]
    [DisplayFormat(DataFormatString = "{0:0.00}", ApplyFormatInEditMode = true)]
    //calculated property
    public virtual double TotalSubTaskCost
    {
        get
        {
            if (Subtasks == null)
                return 0;
            if (!Subtasks.Any())
                return 0;
            double it = Subtasks.Where(a => a != null).
                Aggregate<Subtask, double>
                    (0, (current, a) => current + a.TotalCost);
            return it;
        }
    }
 }

每当Task查询其TotalSubtaskCost时,它都会执行计算。每个子任务都有自己的属性TotalCost。因此,我们对子任务的这些值进行汇总和求和。由于Task总是知道它自己的子任务,所以计算应该总是正确的。