Skip to content

Latest commit

 

History

History
88 lines (68 loc) · 3.34 KB

11. Mapping.md

File metadata and controls

88 lines (68 loc) · 3.34 KB

Mapping

As we've seen, the separation between entity classes and DTO/ViewModel classes does involve some code which must move data from one (or more) object(s) to another:

  var result = from c in _courses.All()
  where x.Semester == "20143"
  select new CourseDTO
  {
    // TODO: map properties from c to the CourseDTO object!
  }

For small classes (with few properties), this may not be that much of an issue. However, if one of the following applies:

a) there are many properties to map to/from, b) the mapping needs to happen in several places, c) the classes in question might be prone to changes, i.e. we might want to add properties to them which must be mapped then this could be an issue.

In that case, we should try to move mapping to a central place. This could involve a custom (hand-written) routine, perhaps as an extension method:

public static class CourseExtensions
{
  public static IEnumerable<CourseDTO> ToDTO(this IEnumerable<Course> courseEntities)
  {
    return courseEntities.Select(c => c.ToDTO());
  }
  
  public static CourseDTO ToDTO(Course c)
  {
    return new CourseDTO
    {
      // TODO: map properties from c to the CourseDTO object!
    };
  }

This could quickly become tedious, especially when the mapping is trivial.

Some solutions have been developed which make this a bit easier, such as AutoMapper. Using AutoMapper, we need to specify at startup that we wish to be able to map between certain types:

Mapper.CreateMap<Course, CourseDTO>();

This step is necessary for performance reasons. AutoMapper reads the information about each type and what properties can be mapped, but this is time-consuming and would slow down our code if this would be done each time we would need to map between two objects.

An elegant way to setup the mapping for each layer of our project is to add a mapping file to the App_Start folder. Inside the file we can add our mappings within a static class and method:

public static class ConfigureMapping
{
	public static void Configure()
	{
		Mapper.CreateMap<Course, CourseDTO>();
	}
}

Then to register the mappings we must add a call to the method within the Application_Start method in the global.asax file:

protected void Application_Start()
{
	// Default generated code is not shown
	ConfigureMapping.Configure();
}

Then, when the need arises to map between two types, we can do so using the following code:

var courseDTO = Mapper.Map<CourseDTO>(c);

It is necessary to install AutoMapper via the Package Manager for each project that will be using any mappings. This adds the References needed for AutoMapper to work correctly.

AutoMapper is also capable of various things, such as performing projections at the IQueryable level, resulting in less data being requested from the server. This is achieved using AutoMapper Projections.

Then there are those that say we should avoid tools such as AutoMapper. There are also a few reasons why a DTO->Entity mapping might be a bad idea. As with so many techniques, they may be appropriate in some places but hardly all.