2

这是我在阅读了很多关于 DDD、TDD 和 Repository / UnitOfWork 模式之后的第一次尝试,以制作我自己的应用程序。

我在 .NET 4.0 上使用实体框架、MVC 4(将运行此应用程序的服务器是 Windows 2003)

这是基本的简化模式逻辑(原始模式使用 IRepository、IUnitOfWork、GenericRepository 并使用 IEntity 接口扩展 EF POCO 以提供对公共 ID 字段的访问。但这个简化的示例足以提出我的问题)

View -> ViewModel -> Controller <- UnitOfWork <- Repository <- EntityFramework <- Database

看法

Model.Employee.GetSeniority()

EmployeeDetailsViewModel

Employee e { get; set; }

员工

DateTime dateHired { get; set; }
TimeSpan GetSeniority()
{
    return DateTime.Today - dateHired;
}

控制器 EmployeeDetails()

using(var unitOfWork = new UnitOfWork) {
    return View(EmployeeDetailsViewModel model = new EmployeeDetailsViewModel {
        e = unitOfWork.GetEmployeRepository().Find(o=>o.id == id)
    });
}

UnitOfWork GetEmployeRepository()

return (_employeeRepository ?? _employeeRepository = new EmployeeRepository(this.dbContext));

存储库查找()

dbContext.Configuration.EnableProxyCreation = false;
Employee e = dbContext.Employees.Where(expression);
dbContext.Configuration.EnableProxyCreation = true;
return e;

一切实际上都正常工作。问题是我觉得这里有些地方很不对劲,我不确定应该在哪一层修复它。

在得到很多人(Hi Darin)的建议后,总是将 ViewModels 传递给视图而不是模型,我开始这样做。但是,我正在做的(我认为)并没有好多少。我只是将我的模型封装在视图模型中。起初,这听起来并没有那么糟糕,因为我的 Find() 方法会在获取对象之前关闭代理,这将导致 POCO 不了解持久性。但是,现在我想在 POCO 中添加一些逻辑,我觉得有什么问题。

我认为问题出在我的业务逻辑所在的位置以及我的 Employee POCO 应该映射到 DTO 对象的事实。但是,我应该在哪里将 Employee POCO 转移到 EmployeeDTO?那应该是存储库、控制器还是其他什么的任务?我也不确定我应该把我的业务逻辑放在哪里(就像示例中显示的 GetSeniority() 一样简单)。应该通过部分类将其添加到 EF POCO 中还是应该在 DTO 中?或者 Employee -> EmployeeDTO 转移中是否还有另一个缺失的步骤?

4

1 回答 1

3

这是一个很好的问题。看起来您正在尝试找到非常棒的干净分离。我会解决这个问题。你有数据访问,你有 UI 显示,在两者之间你有你的业务逻辑。如果您想使用域模型方法,我将如何构建它。

  • 永远不要在存储库之外公开 EntityFramework 实体类。您可以选择从存储库返回 Dto (POCO') 或域对象。如果您希望 Dto 进行更多分离,那很好,您只需要另一个层(例如服务层)将 Dto 转换为域对象。

  • 将您的业务逻辑放入您的域对象中。因此 Domain.Employee.GetSenority() 将在您的域对象上。

  • 任何不适合您的域对象的逻辑都可以驻留在您的 UnitOfWork 或服务层中。

  • 在控制器中将域对象转换为 ViewModel。此时将 Employee.GetSenority() 映射到 MyViewModel.Senority 属性。基本上,您的 ViewModel 是一个 Dto,仅包含通常不多的视图特定逻辑。

  • 你在哪里调用存储库。您可以使用 UnitOfWork 模式,也可以简单地创建一个服务层类。这里的关键是这些应该可用于其他应用程序类型。例如,如果您要编写桌面或 Windows 8 风格的应用程序,您可能希望将其中任何一个与您的域实体一起重用。

我相信你对此很开心。祝你好运。

于 2012-10-16T16:14:25.723 回答