为包含多个数据库表的视图创建视图模型 (MVC 4)

Creating a ViewModel for a View consisting of multiple database tables (MVC 4)

假设我有三个数据库 tables:Zoo、Animal 和 ZooAnimal,看起来像这样:

// Zoo //
int ID
string Name

// Animal //
int ID
string Name
string Genus
string Species

// ZooAnimal //
int ID
int ZooID
int AnimalID

我想创建一个显示 table 的视图,其中包含每个动物园中存在的动物,如下所示:

+------------+--------+----------+-----------+
| Zoo        | Animal | Genus    | Species   |
+============+========+==========+===========+
| Oregon Zoo | Lion   | Panthera | P. leo    |
+------------+--------+----------+-----------+
| Oregon Zoo | Tiger  | Panthera | P. tigris |
+------------+--------+----------+-----------+

如果这只是一个 table,那就简单了。一个带有 EditorFor 或 DisplayFor 的 ViewModel。但是由于 ViewModel 中显示的数据跨越多个 table 连接在一起,我该如何组织它?

到目前为止,我研究过使用单独的 ViewModel 和 DomainModel classes。三个域模型 classes(用于 Zoo、Animal 和 Animal Zoo)和一个 ViewModel class(用于 "AnimalsByZoo" 视图)。

// AnimalInZoo ViewModel //
string Zoo
string Animal
string Genus
string Species 

我的 DomainModel classes 将由 DbContext 填充,但是如何使用存储在 DomainModel 中的值填充我的 ViewModel 数据?我的 ViewModel 是否需要每个 DomainModel 一个字段?

// AnimalInZoo ViewModel //
[same fields as above]
Zoo ZooDomainModel
Animal AnimalDomainModel
ZooAnimal ZooAnimalDomainModel

这似乎很合理,但这是否违反了 ViewModel 仅具有要显示在屏幕上的元素的想法?

您可以使用Automapper。这是一个非常易于使用的库,可让您映射对象。所以,您只需要:

  1. 安装包

    PM> 安装包 AutoMapper

  2. 注册映射

    AutoMapper.Mapper.CreateMap(); AutoMapper.Mapper.CreateMap();

  3. 地图

    var objModel = Mapper.Map(objData);

您可以在此处找到更详细的信息http://automapper.org/

在我看来,最好是转换数据,这样您的 ViewModel 就会有一个 IEnumerable,而在每个 Zoo 对象中都有一个 IEnumerable。适合展示且易于使用。

ViewModel 用于表示视图工作所需的数据。您拥有用户 create/edit/delete 或仅显示所需的属性。您还将通过添加 DataAttributes 为这些属性定义规则,以便您可以执行 model validation。你永远不应该 return 你的域模型到你的视图中。

您可以使用一个包含每个域模型所需的所有属性的模型,从而创建一个 ViewModel。如果所有这些属性都是简单的属性,并且您需要将它们全部填写以创建您的 AnimalsByZoo,那么这可能是可行的方法。如果您只需要它来显示数据,这也应该足够了。 作为 Gabriel said, you could use AutoMapper 在您的 DM 和 VM 之间来回映射。

AnimalsByZooVM animalsByZoo = Mapper.Map<AnimalsByZooVM>(dbData);

但是,如果您的视图稍微复杂一些,或者您觉得出于某种原因需要将其拆分,则可以创建 3 个 VM。使用 3 个 VM 来表示 2 个表可能会很强大,因为您可以拥有一个 AnimalVM 和一个 ZooVM。然后,您创建一个 AnimalZooVM 来保存其他两个 ViewModel,甚至是您出于某种原因需要显示或保存的其他属性。

public class AnimalZooVM
{
    public ICollection<AnimalVM> Animals { get;set; }
    public ICollection<ZooVM> Zoos { get;set; }
    public int ZooAnimalId { get;set; }
}

如果您有这样的 ViewModel,则可以使用 AutoMapper 以这种方式将 DM 映射到 VM

AnimalZooVM vm = new AnimalZooVM();
vm.Animals = Mapper.Map<AnimalVM>(dbData);
vm.Zoos = Mapper.Map<ZoosVM>(dbData);