C# 从数据库填充域实体
我的代码中有很多类似的东西(这只是一个简单的示例): 而C# 从数据库填充域实体,c#,entity-framework,domain-driven-design,lazy-loading,eager-loading,C#,Entity Framework,Domain Driven Design,Lazy Loading,Eager Loading,我的代码中有很多类似的东西(这只是一个简单的示例): 而Invoice将字段UnpaidAmount计算为 public double UnpaidAmount { get { return OrderLines.Sum(ol => ol.Amount) - Payments.Sum(p => p.Amount); } } 现在,项目中经常发生的情况是,如果有人需要修改UnpaidAmount逻辑,例如: ret
Invoice
将字段UnpaidAmount
计算为
public double UnpaidAmount
{
get
{
return OrderLines.Sum(ol => ol.Amount) -
Payments.Sum(p => p.Amount);
}
}
现在,项目中经常发生的情况是,如果有人需要修改UnpaidAmount
逻辑,例如:
return OrderLines.Sum(ol => ol.Amount) -
Payments.Sum(p => p.Amount) -
CreditNotes.Sum(cn => cn.Amount);
然后,他们需要在项目中使用UnpaidAmount
的任何地方找到,并在获取发票时将CreditNotes
添加到Include
。人们经常忘记这一点,在这种情况下,CreditNotes
上的Sum
实际上会在一个空集合上被调用,而不是在从数据库获取的集合上
这会变得很麻烦,很难通过项目来维护
另一种选择是要么丢失懒散加载
,这样我们就不必考虑包含在任何地方,但这可能会导致性能问题,这些问题可能在开发过程中检测不到,但在以后的生产中,当获取的记录数变大时会检测到
或者使用一种方法获取Invoice
对象及其所有导航属性+递归地获取对象图中更深的导航属性。但这太过分了,因为很多不需要的东西每次都会被拿走
我想这是我必须做出的权衡,但我需要的是那些在大型项目中遇到此类问题的人的建议,你们认为什么样的解决方案最适合长期维护 可以提供引入某种类型的商店,例如发票。它将在构造函数中获取DbContext,并提供获取和保存发票所需的所有方法。所以,您只有一个地方可以编写和修改查询
class Invoices
{
public Invoices(DbContext dbContext){....}
public Invoice GetInvoiceById(int invoiceId)
{
return this.dbContext.Invoices
.ForId(invoiceId)
.Include(i => i.Payments)
.Include(i => i.OrderLines)
.FirstOrDefault();
}
...
然后,他们需要在项目中找到使用UnpaidAmount的所有地方,并在获取发票时添加CreditNotes
为什么这种责任存在于不止一个地方
另一种方法是要么丢失懒散加载,这样我们就不必考虑包含在任何地方,但这可能会导致性能问题,这些问题可能在开发过程中检测不到,但在以后的生产过程中,当获取的记录数变大时会检测到
或者使用一个方法获取Invoice对象及其所有导航属性+递归地获取对象图中更深的导航属性。但这太过分了,因为很多不需要的东西每次都会被拿走
我认为您正在寻找的是存储库模式
基本思想是:
您有一个或多个用户可以用来描述他们将如何使用发票(或者,发票的哪个视图满足他们的需求)
您提供了这些角色的实现,这些角色对发票数据的存储方式有共同的理解。这意味着,当您将CreditNotes引入模型时,只有一个地方需要更改
您可以使用管道(依赖项注入或其他方式)来确保为每个角色提供正确的实现
简而言之,您在消费者和供应商之间创建了一个明确的合同;消费者描述他们需要什么,供应商可以自由选择如何满足需求
乌迪·达汉(Udi Dahan)在当天写了几篇与这个想法相关的帖子
class Invoices
{
public Invoices(DbContext dbContext){....}
public Invoice GetInvoiceById(int invoiceId)
{
return this.dbContext.Invoices
.ForId(invoiceId)
.Include(i => i.Payments)
.Include(i => i.OrderLines)
.FirstOrDefault();
}
...