为包含多个数据库表的视图创建视图模型 (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。这是一个非常易于使用的库,可让您映射对象。所以,您只需要:
安装包
PM> 安装包 AutoMapper
注册映射
AutoMapper.Mapper.CreateMap();
AutoMapper.Mapper.CreateMap();
地图
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);
假设我有三个数据库 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。这是一个非常易于使用的库,可让您映射对象。所以,您只需要:
安装包
PM> 安装包 AutoMapper
注册映射
AutoMapper.Mapper.CreateMap(); AutoMapper.Mapper.CreateMap();
地图
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);