AutoMapper, ProjectTo() – Static Version

Full source code available here.

I’ve been using AutoMapper for quite a few years, but one of the features that I like the most is the ProjectTo method. When using Entity Framework it lets me reduce the number of fields I query from the database to match the model I want to return to the caller.
For example, I have a Product table in the database and a DTO that represents the Product that looks like this –

public class Product
{
	public int ProductId { get; set; }
	public string Name { get; set; }
	public ProductCategory ProductCategory { get; set; }
	public string Description { get; set; }
	public decimal Price { get; set; }
	public string SKU { get; set; }
	public string Code { get; set; }
}  

But say I wanted to return only the ProductId, Name and Code, I could run a query to return the full Product and the map the results to a model that looks like this –

public class ProductModel
{
	public int ProductId { get; set; }
	public string Name { get; set; }
	public string Code { get; set; }
}

In this scenario, the generated SELECT statement will request all seven fields in product and return them to the application, I then have to them to the ProductModel with the three fields I want.
Here is the SQL produced an executed –

SELECT TOP(@__p_0) [p].[ProductId], [p].[Code], [p].[Description], [p].[Name], [p].[Price], [p].[ProductCategory], [p].[SKU]
FROM [Products] AS [p]
ORDER BY [p].[ProductId]

Instead of requesting all seven fields the ProjectTo method will examine the model and generate only the SQL needed to return the relevant fields.

Here is the SQL produced –

SELECT TOP(@__p_0) [p].[Code], [p].[Name], [p].[ProductId]
FROM [Products] AS [p]
ORDER BY [p].[ProductId]

And here is how to write the C# code that performs this time saving, energy saving work –

var productModels = _salesContext.Products.OrderBy(p => p.ProductId).Take(count).ProjectTo<ProductModel>();

To get this to work you need to do some wiring up.
First add the nuget package AutoMapper.Extensions.Microsoft.DependencyInjection v6.1.1 to your project.

Then create a mapping profile, for this scenario it is very simple. The below code maps Product to ProductModel.

public class MappingProfile : Profile
{
	public MappingProfile()
	{
		CreateMap<Product, ProductModel>();
	}
}

In starup.cs add a call to Mapper.Initialize as shown here.

public void ConfigureServices(IServiceCollection services)
{
	Mapper.Initialize(cfg => {
		cfg.AddProfile<MappingProfile>();
	});

That’s all you need, but that’s not the end of the story…

This approach works with AutoMapper.Extensions.Microsoft.DependencyInjection up to v6.1.1, and AutoMapper v8.1.1, but if you move to newer versions you need a slightly different approach because the static API has been removed.

I’ll show that in the next blog post.

Full source code available here.

One thought on “AutoMapper, ProjectTo() – Static Version

  1. Pingback: AutoMapper, ProjectTo() – Instance Version | no dogma blog

Leave a Reply

Your email address will not be published. Required fields are marked *