In most multi-layer systems, there are at least two instances of each database object (or entity). These "instances" are POCOs (Plain Old Class Objects) and are simply classes. These POCOs are used in different parts of the application and have different purposes.
POCOs
For example, a User POCO might be used in the repository layer of the system. The User class might look something like this.
- namespace App.Domain
- {
- public partial class User
- {
- public int Id { get; set; }
- public string UserName { get; set; }
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string Email { get; set; }
- public bool IsVisible { get; set; }
- }
- }
The fields of the User POCO are drawn from the database and reflect the structure of the User table. However, when we want to use User data in the UI layer, we may want to incorporate more fields or decorations (annotations) to store additional information used within the UI. Therefore, we need another User POCO which we can modify and that does not impact the data layer POCO. These UI POCOs are often referred to as ViewModels.
ViewModels
General ViewModel best practice says that we should prefix the POCO name with ViewModel. For example, the data POCO would be called User, whereas the UI POCO would be called ViewModelUser. The ViewModelUser POCO might look something like this.
- namespace App.Web.Models
- {
- public partial class ViewModelUser
- {
- [Required("This is required")]
- [DisplayBrand("Id")]
- public int Id { get; set; }
- [Required("This is required")]
- [StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
- [Display("UserName")]
- public string UserName { get; set; }
- [Required("This is required")]
- [StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
- [Display("FirstName")]
- public string FirstName { get; set; }
- [Required("This is required")]
- [StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
- [Display("Surname")]
- public string LastName { get; set; }
- [Required("This is required")]
- [StringLength(100, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
- [Display("Email")]
- [RegularExpressEmailAttribute]
- [DataType(DataType.EmailAddress)]
- public string Email { get; set; }
- [Required("This is required")]
- [Display("Active?")]
- public bool IsVisible { get; set; }
- }
- }
Now, a problem presents itself. When we are working with Controllers and Builders in our UI, we need to pass POCOs to the data layer. But our UI POCOs are not the same as our data POCOs. Even though we know that the User and ViewModelUser POCOs are essentially the same, our code does not know. So we need to tell it. How do we pass POCOs from our UI builders to our business builders when the parameter types do not match? This is where our Object Mapper comes into play.
We could do something like this.
- namespace App.Web.Models
- {
- public class ViewModelUserBuilder : IViewModelUserBuilder
- {
- private readonly IUserBusiness _userBusiness;
- public ViewModelUserBuilder(IUserBusiness userBusiness)
- {
- _userBusiness = userBusiness;
- }
- public List<ViewModelUser> GetAllUsers()
- {
- List<User> model = _userBusiness.GetAllUsers().ToList(); // returns a list of Users (data POCOs)
- List<ViewModelUser> entities = new List<ViewModelUser>(); // create a list of ViewModelUser (UI POCOs)
- foreach(User user in model)
- {
- // loop through the data POCOs and create an instance of a UI POCO
- ViewModelUser entity = new ViewModelUser(){
- Id = user.Id,
- UserName = user.UserName,
- FirstName = user.FirstName,
- LastName = user.LastName,
- Email = user.Email,
- IsVisible = user.IsVisible
- }
- entities.Add(entity); // Add the UI POCO to the list
- }
- return entities; // return the UI POCO list for use in the UI
- }
- }
- }
Object Mapper
That seems like a lot of work, right? AutoMapper can make that whole process so much easier. It's as simple as creating an instance of each object (or list of objects), passing them into the mapping engine and returning the transformed object(s). Let me show you the above code using AutoMapper.
- namespace App.Web.Models
- {
- public class ViewModelUserBuilder : IViewModelUserBuilder
- {
- private readonly IUserBusiness _userBusiness;
- public ViewModelUserBuilder(IUserBusiness userBusiness)
- {
- _userBusiness = userBusiness;
- Mapper.CreateMap<ViewModelUser, User>();
- Mapper.CreateMap<User, ViewModelUser>();
- }
- public List<ViewModelUser> GetAllUsers()
- {
- var entities = new List<ViewModelUser>();
- var model = _userBusiness.GetAllUsers().ToList();
- entities = Mapper.Map(model, entities); // Let automapping "merge" the two objects
- return entities;
- }
- }
- }
The order that you pass the POCOs into the Mapper.Map method does matter. The POCO on the left is the source type, and the one on the right is the destination type and the mapping works because both POCOs have the same field names. So, the mapping looks in the source POCO, then looks in the destination POCO for a corresponding field. If it finds a match, it merges the data from the source into the destination. It does not alter the source, so you can still use it if you want. But the destination POCO is presented in a useful way for you to work with.
Till next time .

Gowtham RajamanickamPosted May 26, 2015, 9:02 AM
Good one
Vithal WadjePosted Apr 9, 2015, 2:20 PM
nice one