MVC存储库 - 域模型与实体模型

时间:2011-07-21 19:37:02

标签: c# .net asp.net-mvc asp.net-mvc-3 repository-pattern

我创建了一个使用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

我有一个返回项目的存储库:

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 - &gt;资源跳跃。 ProjectResource将包含我需要的字段。而不是做类似的事情:

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

我能做到:

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

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

3 个答案:

答案 0 :(得分:5)

我自己的观点是,您不应该向控制器或依赖于存储库实现的视图返回任何内容。

如果您将EF与POCO Generator一起使用,那么将这些类用于您的域模型是合理的,因为它们独立于EF实现(您可以替换EF并保留POCO)。

但是,如果您将EF与其EntityObjects一起使用,我相信您应该转换为您的域模型。如果您的数据访问封装在内部使用存储库模式的WCF服务中,我不会太担心从存储库返回EntityObjects。但是,如果您直接从MVC使用存储库,请使用域模型作为存储库的接口。

答案 1 :(得分:3)

我们倾向于始终使用ViewModel作为“中间的类”,并使用...来映射到实际模型和从中映射...

Automapper

...或...

ValueInjecter

如果您愿意,您的ViewModel可以在结构方面完全独立于您的模型。

答案 2 :(得分:-1)

您所描述的正是我多年来一直在做的事情,因为他们要遵循n层应用程序设计。

因为您的数据并不总是以与您的域相同的方式进行组织。在SQL中,因为你在这里遇到的结果并不总是相同的。

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

我会说,在中间(您的业务层)有一些简短的答案,并且公开了控制器可用于接收数据的方法。