Ryan O'Neill
Ryan O'Neill

Reputation: 5687

AutoMapper ProjectUsing not being called

I'm trying to use the ProjectUsing feature of AutoMapper to only select the columns I need through a LINQ expression but it seems the expression itself does not get called at run-time or via unit testing.

As a test I am just putting a fixed value into the AlternateId property but the assert below always fails. This also fails with single instances (not in a queryable list) and at run-time via Entity Framework 6.

    class MapFrom
    {
        public int Id { get; set; }
    }
    class MapTo
    {
        public int AlternateId { get; set; }
    }

    [TestMethod]
    public void Automapper_projectusing_test()
    {
        AutoMapper
            .Mapper
            .CreateMap<MapFrom, MapTo>()
            .ProjectUsing(src => new MapTo { AlternateId = 88 });
        var products = new List<MapFrom>();
        products.Add(new MapFrom());

        var mapped = products
            .AsQueryable()    // Just in case ProjectUsing only works with IQueryable.
            .Project()
            .To<MapTo>()
            .ToList();

        Assert.AreEqual(88, mapped.Single().AlternateId); // Fails, AlternateId equals 0.
    }

Using AutoMapper v3.3.1, NCrunch confirms that the mapping expression code is never executed.

Why is AutoMapper not executing this expression, perhaps I'm missing a key step?

Upvotes: 0

Views: 1093

Answers (2)

Ryan O&#39;Neill
Ryan O&#39;Neill

Reputation: 5687

According to Jimmy Bogarde 'This works as designed, you want ConstructUsing.'. See https://github.com/AutoMapper/AutoMapper/issues/677#event-289561571

Obviously it's caught us all out so I think the documentation could be clearer here.

Upvotes: 1

twifosp
twifosp

Reputation: 287

I was trying to do the same thing and came across this issue and could not figure it out either. I downloaded the Automapper source and had a look at the associated tests.

    public ProjectEnumTest()
    {
        Mapper.CreateMap<Customer, CustomerDto>();
        Mapper.CreateMap<CustomerType, string>().ProjectUsing(ct => ct.ToString().ToUpper());
    }

    [Fact]
    public void ProjectingEnumToString()
    {
        var customers = new[] { new Customer() { FirstName = "Bill", LastName = "White", CustomerType = CustomerType.Vip } }.AsQueryable();

        var projected = customers.Project().To<CustomerDto>();
        projected.ShouldNotBeNull();
        Assert.Equal(customers.Single().CustomerType.ToString().ToUpper(), projected.Single().CustomerType);
    }

The short answer is this only appears to work on member level mappings and not first class level mappings? Substituting the mapping with below does not work. The projected value is just a CustomerDto object with null properties.

 Mapper.CreateMap<Customer, CustomerDto>().ProjectUsing(c => new CustomerDto{FirstName = "Test"});

From the article listed here: http://lostechies.com/jimmybogard/2014/12/23/automapper-3-3-feature-projection-conversions/ I would assume the above functionality might be intended, but does not work. Either that, or there is a configuration problem with both our understanding of how this works.

Upvotes: 0

Related Questions