业务逻辑应该在这种模式中的哪个位置?

时间:2012-10-16 15:47:33

标签: asp.net-mvc entity-framework design-patterns domain-driven-design repository-pattern

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

我在.NET 4.0上使用Entity Framework,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;
}

Controller 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传递给视图而没有模型,我开始这样做了。但是,我正在做的事情(我认为)并没有好多少。我只是将我的模型封装在一个viewmodel中。起初,它听起来并不坏,因为我的Find()方法会在获取对象之前关闭代理,这会导致持久性无知的POCO。但是,现在我想在POCO中添加一些逻辑,我觉得有些不对劲。

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

1 个答案:

答案 0 :(得分:3)

这是一个很好的问题。看起来你正试图寻找清晰的分离,这太棒了。我会打破这个问题。您拥有数据访问权限,并且您具有UI显示功能,并且在您之间具有业务逻辑。如果你想使用域模型方法,我将如何构建它。

  • 永远不要在Repository之外公开EntityFramework Entity类。您可以选择从存储库返回Dto(POCO')或Domain对象。如果你想让Dto更多分离,那就没问题,你只需要另一层,比如服务层,就可以将Dto转换为域对象。

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

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

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

  • 您在哪里调用存储库。您可以使用UnitOfWork模式,也可以只创建服务层类。这里的关键是这些应该可用于其他应用程序类型。例如,如果您要编写桌面或Windows 8样式应用程序,则可能需要重复使用其中任何一个以及域实体。

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