gpt4 book ai didi

c# - 领域模型及相关数据(贫血领域模型)

转载 作者:太空狗 更新时间:2023-10-29 23:29:11 25 4
gpt4 key购买 nike

我目前正在使用 Entity Framework Core 处理 ASP .NET Core 1.0。我对数据库中的数据进行了一些复杂的计算,我不确定如何使用依赖注入(inject)构建适当的架构而不构建贫血域模型(http://www.martinfowler.com/bliki/AnemicDomainModel.html)

(简化)示例:

我有以下实体:

public class Project {
public int Id {get;set;}
public string Name {get;set;}
}

public class TimeEntry
{
public int Id {get;set;}
public DateTime Date {get;set;}
public int DurationMinutes {get;set;}
public int ProjectId {get;set;}
public Project Project {get;set;}
}

public class Employee {
public int Id {get;set;}
public string Name {get;set;}
public List<TimeEntry> TimeEntries {get;set;}
}

我想做一些复杂的计算来计算月度时间表。因为我无法访问 Employee 实体中的数据库,所以我在 EmployeeService 中计算了 TimeSheet。

public class EmployeeService {
private DbContext _db;
public EmployeeService(DbContext db) {
_db = db;
}

public List<CalculatedMonth> GetMonthlyTimeSheet(int employeeId) {
var employee = _db.Employee.Include(x=>x.TimeEntry).ThenInclude(x=>x.Project).Single();
var result = new List<CalculatedMonth>();

//complex calculation using TimeEntries etc here

return result;
}
}

如果我想获取 TimeSheet,我需要注入(inject) EmployeeService 并调用 GetMonthlyTimeSheet

所以 - 我最终在我的服务中使用了很多 GetThis() 和 GetThat() 方法,尽管这些方法完全适合 Employee 类本身。

我想要实现的是:

public class Employee {
public int Id {get;set;}
public string Name {get;set;}
public List<TimeEntry> TimeEntries {get;set;}

public List<CalculatedMonth> GetMonthlyTimeSheet() {
var result = new List<CalculatedMonth>();

//complex calculation using TimeEntries etc here

return result;
}
}

public IActionResult GetTimeSheets(int employeeId) {
var employee = _employeeRepository.Get(employeeId);
return employee.GetTimeSheets();
}

...但是为此我需要确保从数据库中填充 TimeEntries 列表(EF Core 不支持延迟加载)。我不想在每个请求中.Include(x=>y) 一切,因为有时我只需要没有时间条目的员工姓名,这会影响应用程序的性能。

任何人都可以指出如何正确构建它的方向吗?

编辑:一种可能性(来自第一个答案的评论)是:

public class Employee {
public int Id {get;set;}
public string Name {get;set;}
public List<TimeEntry> TimeEntries {get;set;}

public List<CalculatedMonth> GetMonthlyTimeSheet() {
if (TimeEntries == null)
throw new PleaseIncludePropertyException(nameof(TimeEntries));

var result = new List<CalculatedMonth>();

//complex calculation using TimeEntries etc here

return result;
}
}

public class EmployeeService {
private DbContext _db;
public EmployeeService(DbContext db) {
_db = db;
}

public Employee GetEmployeeWithoutData(int employeeId) {
return _db.Employee.Single();
}

public Employee GetEmployeeWithData(int employeeId) {
return _db.Employee.Include(x=>x.TimeEntry).ThenInclude(x=>x.Project).Single();
}
}

public IActionResult GetTimeSheets(int employeeId) {
var employee = _employeeService.GetEmployeeWithData(employeeId);
return employee.GetTimeSheets();
}

最佳答案

不要尝试用聚合来解决查询问题。您的聚合旨在处理命令并保护不变量。它们围绕一组数据形成了一致性边界。

Employee 对象是否负责保护员工时间表的完整性?如果不是,则此数据不属于 Employee 类。

延迟加载对于 CRUD 模型可能没问题,但在我们设计聚合时通常被认为是一种反模式,因为聚合应该尽可能小且具有内聚性。

您是否根据时间表的计算结果做出业务决策?是否有任何不变量需要保护?如果决策是根据过时的时间表数据做出的,这有关系吗?如果这些问题的答案是,那么您的计算实际上只不过是一个查询。

在服务对象中放置查询很好。这些服务对象甚至可能存在于领域模型之外(例如在应用层),但没有严格的规则可循。此外,您可以选择加载一些聚合以访问处理计算所需的数据,但通常最好直接进入数据库。这样可以更好地分离读取和写入 (CQRS)。

关于c# - 领域模型及相关数据(贫血领域模型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40737971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com