MVC仓库 - 领域模型 vs 实体模型

5

我已经创建了一个仓库,使用Entity Framework从我的数据库中返回数据,现在需要将这些数据提供给我的视图,但在此之前,我需要将这些对象转换为我的领域模型。

我的架构看起来像这样:

TABLE Project
    Id INT PRIMARY KEY
    Name NVARCHAR(100)

TABLE Resource
    Id INT PRIMARY KEY
    FirstName NVARCHAR(100)
    LastName NVARCHAR(100)

TABLE ProjectResources
    Project_Id INT PRIMARY KEY   -- links to the Project table
    Resource_Id INT PRIMARY KEY  -- links to the Resource table

我生成了一个实体模型,它看起来像这样:

Project
|
---->ProjectResources
     |
     ---->Resource

我有一个返回Project的代码库:

public interface IProjectRepository
{
    Project GetProject(int id);
}

一个控制器动作:

public ActionResult Edit(int id)
{
    Project project = projectRepository.GetProject(id);

    return View(project);
}

当我尝试使用POST方法提交这些数据时,似乎并不起作用。在尝试重构ProjectResources集合时,我遇到了一个EntityCollection已初始化的错误。

我认为创建一个更简单的领域模型会更明智:

public class ProjectEdit
{
    public string ProjectName { get; set; }
    public List<ProjectResource> Resources { get; set; }
}

public class ProjectResource
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

这个方法更好一些,因为我不需要进行中间的ProjectResources -> Resource跳转,直接使用ProjectResource就可以获取所需字段。不需要像下面这样做:

@foreach( var resource in Model.ProjectResources ) {
    @Html.DisplayFor(m => m.Resource.FirstName)
}

我可以做到:

@foreach( var resoure in Model.Resources ) {
    @Html.DisplayFor(m => resource.FirstName);
}

我的问题如下 我应该从我的存储库返回域模型,还是应该由控制器或其他中间类处理?如果它在控制器中由将我的项目映射到ProjectEdit的东西处理,那会是什么样子?

3个回答

5
我的观点是,你不应该返回任何与存储库实现有关的内容给控制器或视图。
如果你使用带有POCO生成器的EF,那么使用这些类作为你的领域模型是合理的,因为它们不依赖于EF实现(你可以替换EF并保留POCO)。
但是,如果你使用EF及其EntityObjects,则应将其转换为你的领域模型。如果你的数据访问被封装在一个使用存储库模式的WCF服务中,我就不会太担心从存储库返回EntityObjects。但是,如果你直接从MVC使用存储库,请使用领域模型作为存储库的接口。

那么你的意思是我的存储库应该返回领域模型而不是实体模型? - Dismissile
如果您的存储库没有封装在单独的服务中,是的。 - Steve Morgan

3
我们通常使用ViewModel作为“中间层的类”,并使用AutomapperValueInjecter来映射实际Model,这样你的ViewModel就可以相对独立于Model的结构。请注意保留HTML标签。

-1

你所描述的正是我多年来一直在做的事情,努力遵循n层应用程序设计。

因为你的数据不总是与你的领域相同的组织方式。 SQL中有意义的东西,在你的领域中并不总是相同的,就像你在这里遇到的一样。

通常,我的领域知道存储库的样子,并具有将其转换为和从其中转换的方法。我的UI/视图知道领域的外观,并具有检索数据的方法(放在控制器中)。

因此,简短的回答是,我会说,在中间层(您的业务层)做些什么,并使其公开可供控制器使用的方法来接收该数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接