Reputation: 3003
Say I have three database tables: Zoo, Animal, and ZooAnimal that look something like this:
// Zoo //
int ID
string Name
// Animal //
int ID
string Name
string Genus
string Species
// ZooAnimal //
int ID
int ZooID
int AnimalID
I want to create a View that shows a table containing the animals that exist in each zoo, like so:
+------------+--------+----------+-----------+
| Zoo | Animal | Genus | Species |
+============+========+==========+===========+
| Oregon Zoo | Lion | Panthera | P. leo |
+------------+--------+----------+-----------+
| Oregon Zoo | Tiger | Panthera | P. tigris |
+------------+--------+----------+-----------+
If this were just one table, then that's simple. One ViewModel with an EditorFor or DisplayFor. But since the data shown in the ViewModel spans multiple tables joined together, how do I go about organizing this?
So far, I've looked into having separate ViewModel and DomainModel classes. Three domain model classes (for Zoo, Animal, and Animal Zoo), and one ViewModel class (for an "AnimalsByZoo" view).
// AnimalInZoo ViewModel //
string Zoo
string Animal
string Genus
string Species
My DomainModel classes will be populated by a DbContext, but how do I populate my ViewModel data with the values stored in the DomainModel? Does my ViewModel need one field per DomainModel?
// AnimalInZoo ViewModel //
[same fields as above]
Zoo ZooDomainModel
Animal AnimalDomainModel
ZooAnimal ZooAnimalDomainModel
That seems reasonable, but doesn't that violate the idea of ViewModels only having elements that are to be displayed on the screen?
Upvotes: 2
Views: 2972
Reputation: 900
ViewModels are used to represent the data that you need for a view to work. You have the properties that you need for the user to create/edit/delete or just show. You will also define rules for those properties by adding DataAttributes, so that you can perform model validation. You should never return your domain model to your view.
You can use one model containing all the properties that you need from each domain model, thus creating a ViewModel. If all those properties are simple properties, and you need them all to be filled out to create your AnimalsByZoo, then this is probably the way to go. If you need it to just display the data, this should also be sufficient. As Gabriel said, you could use AutoMapper to map back and forth between your DMs and VMs.
AnimalsByZooVM animalsByZoo = Mapper.Map<AnimalsByZooVM>(dbData);
However if your view is a little bit more complex, or you feel that you need to split it up for some reason, you can create 3 VMs. Using 3 VMs to represent 2 tables can be powerful in the way that you can have one AnimalVM and one ZooVM. You then create a AnimalZooVM to hold your other two ViewModels, and even other properties that you need to display or hold onto for some reason.
public class AnimalZooVM
{
public ICollection<AnimalVM> Animals { get;set; }
public ICollection<ZooVM> Zoos { get;set; }
public int ZooAnimalId { get;set; }
}
If you have a ViewModel like this, you can then use AutoMapper to map your DMs to your VMs in this manner
AnimalZooVM vm = new AnimalZooVM();
vm.Animals = Mapper.Map<AnimalVM>(dbData);
vm.Zoos = Mapper.Map<ZoosVM>(dbData);
Upvotes: 1
Reputation: 1268
In my opinion it would be the best to transform the data so you'll would have an IEnumerable on your ViewModel and within each Zoo object an IEnumerable. Good for display and easy to use.
Upvotes: 0
Reputation: 4673
You can use Automapper. That is a library very easy to use that allows you to map the objects. So, you just have to:
Install the package
PM> Install-Package AutoMapper
Register the mappings
AutoMapper.Mapper.CreateMap(); AutoMapper.Mapper.CreateMap();
Map
var objModel = Mapper.Map(objData);
You can find more detailed information here http://automapper.org/
Upvotes: 1