N层C#应用程序中计算逻辑的放置位置
我正在使用以下应用程序结构在C#中开发一个N层应用程序 我的解决方案结构N层C#应用程序中计算逻辑的放置位置,c#,wcf,entity-framework,C#,Wcf,Entity Framework,我正在使用以下应用程序结构在C#中开发一个N层应用程序 我的解决方案结构 UI-WPF Prism和ViewModels连接到服务。供商店员工使用 服务-WCF-业务逻辑、数据检索和通过数据层连接到数据库 实体-EF POCO实体-无逻辑 数据-EF DbContext和EDMX-DB连接 Web-ASP.NET MVC应用程序-UI基于Web的版本,功能和客户访问受限。连接到服务 我想知道在哪里有一个实体对象的逻辑,它有计算 下面是示例实体 public class Invoice {
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; }
}
公共类发票
{
public int InvoiceID{get;set;}
公共日期时间发票日期{get;set;}
公共十进制小计{get;set;}
公共十进制?销售税{get;set;}
公共十进制?折扣百分比{get;set;}
公共十进制?折扣装入{get;set;}
公共十进制总数{get;set;}
公共ICollection发票详细信息{get;set;}
}
公共类发票明细
{
public int InvoiceDetailID{get;set;}
public int InvoiceID{get;set;}
公共十进制数量{get;set;}
公共十进制价格{get;set;}
公共十进制总数{get;set;}
公共发票{get;set;}
}
在上述场景中,当值发生变化时,我应该将计算发票总额的逻辑放在何处。例如,更新SalesTax需要更改发票总额。将行项目添加到发票需要更改小计、税金、折扣和总额
我想知道我是否可以在服务层这样做,让实体贫血。我所关心的是,我需要不断地在电线上来回发送整个发票对象
尽管我还没有做一个移动解决方案,但我不确定这在移动环境中是否是一个好主意,因为移动环境可能会因为来回发送发票而消耗数据
例如,另一个想法是在InvoiceDetail中使用AddLineItem()方法,在Invoice中使用CalculateTotals()
AddLineItem会自动计算行项目的总计(我可能会将其设置为DB中的计算列),并计算发票的小计、折扣、税金和总计。我假设在这种情况下,如果我想在内部调用CalculateTotals(),例如当SalesTax发生更改时,而不是让客户端调用CalculateChanges,我可能必须删除自动属性。对吗?如果是的话,这就成了我重构EF模板的一个问题,使其不具有自动属性,而是具有支持字段的属性
请告知哪种方法更好,为什么?或者是一种完全不同的方法。感谢您的帮助。我们的工具出现了一个小问题,并将计算放在域对象本身中。一个对象之所以应该知道它的总数,是因为它知道它的子对象。我们的服务层中使用的业务逻辑特定于业务规则,而不是计算。下面是我们的代码示例(注意:我们将C#.Net与MVC3一起使用):
公共类任务:域库
{
公共虚拟ICollection子任务{get;set;}
[显示(Name=“子任务总成本”)]
[DisplayFormat(DataFormatString=“{0:0.00}”,ApplyFormatInEditMode=true)]
//计算属性
公共虚拟双TotalSubTaskCost
{
得到
{
if(子任务==null)
返回0;
如果(!子任务.Any())
返回0;
double it=子任务。其中(a=>a!=null)。
总数的
(0,(当前,a)=>当前+a.总成本);
归还它;
}
}
}
每当查询任务的TotalSubtaskCost时,它都会执行计算。每个子任务都有自己的属性TotalCost。因此,我们为子任务聚合并求和这些值。由于任务总是知道自己的子任务,因此计算应该总是正确的 我们的工具中存在一个小问题,并将计算放在域对象本身中。一个对象之所以应该知道它的总数,是因为它知道它的子对象。我们的服务层中使用的业务逻辑特定于业务规则,而不是计算。下面是我们的代码示例(注意:我们将C#.Net与MVC3一起使用):
公共类任务:域库
{
公共虚拟ICollection子任务{get;set;}
[显示(Name=“子任务总成本”)]
[DisplayFormat(DataFormatString=“{0:0.00}”,ApplyFormatInEditMode=true)]
//计算属性
公共虚拟双TotalSubTaskCost
{
得到
{
if(子任务==null)
返回0;
如果(!子任务.Any())
返回0;
double it=子任务。其中(a=>a!=null)。
总数的
(0,(当前,a)=>当前+a.总成本);
归还它;
}
}
}
每当查询任务的TotalSubtaskCost时,它都会执行计算。每个子任务都有自己的属性TotalCost。因此,我们为子任务聚合并求和这些值。由于任务总是知道自己的子任务,因此计算应该总是正确的 “使用WCF、EF、Web和WPF的N层应用程序”这不是很好的定义。您的一个层是表示层,您有几个版本吗?您的其中一个层是使用EF连接到的某种数据库。中间还有哪些层?您的设计说明每一层负责什么?使用存储库:@Deniseskimore:我已经根据您的问题更新了项目结构和它们的责任。@Isak…我下面的回答有用吗?您已经回答了自己的问题,您的设计说明说t
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;
}
}
}