Mark
Mark

Reputation: 7818

Automapper query for projecting an anonymous type onto a viewmodel

I have a very basic controller, which does a Linq to Entities query and I want to be able to project the results onto a viewmodel using AutoMapper - however I'm getting the error:

cannot convert from 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.IList<tb.Models.Tour>':

Controller:

var tours2 = (from t in db.Tours
                     join d in db.TourDates on t.TourId equals d.TourId
                     join c in db.TourCategories on t.TourCategoryId equals c.TourCategoryId
                     where d.Date == dte && t.TourCategoryId == id
                     select new
                    {
                        Id = t.TourId,
                        TourName = t.TourName,
                        TourCategoryId = t.TourCategoryId,
                        Bookings = db.Bookings.Where(b => d.TourDateId == b.TourDateId).Count()                            
                    }).ToList();

        Mapper.CreateMap<IList<Tour>, IList<ToursAvail2VM>>();
        IList<ToursAvail2VM> toursvm = Mapper.Map<IList<Tour>, IList<ToursAvail2VM>>(tours2);

ViewModel:

 public class ToursAvail2VM
 {
    public int Id { get; set; }
    public int TourCategoryId { get; set; }
    public string TourName { get; set; }
    public int Bookings { get; set; }
 }

How do I get the list of results projected onto my toursvm class?

Thanks for any advice, Mark

Upvotes: 1

Views: 4604

Answers (2)

Jimmy Bogard
Jimmy Bogard

Reputation: 26785

For this example, I'd use AutoMapper's LINQ projection capabilities.

// This would be somewhere in initialization
Mapper.CreateMap<Tour, ToursAvail2VM>()
    .ForMember(d => d.Bookings, opt => opt.MapFrom(src => 
        src.TourDates.Sum(td => td.Bookings.Count()));

var toursvm = (from t in db.Tours
                 join d in db.TourDates on t.TourId equals d.TourId
                 join c in db.TourCategories on t.TourCategoryId equals c.TourCategoryId
                 where d.Date == dte && t.TourCategoryId == id
                )
              .Project().To<ToursAvail2VM>()
              .ToList();

I'm assuming you include navigation properties in your model here to allow you to navigate from Tour to TourDates to Bookings directly.

Upvotes: 5

Steve Czetty
Steve Czetty

Reputation: 6238

Your linq query is returning an anonymous type, rather than Tour. You need to explicitly specify the class you would like returned, or AutoMapper can't handle it.

However, since you are using Linq to Entities, you can't specify ToursAvail2VM directly. You can do something like selecting into the anonymous type and then immediately selecting into ToursAvail2VM like the following:

IList<ToursAvail2VM> toursvm =
                (from vm in
                    (from t in db.Tours
                     join d in db.TourDates on t.TourId equals d.TourId
                     join c in db.TourCategories on t.TourCategoryId equals c.TourCategoryId
                     where d.Date == dte && t.TourCategoryId == id
                     select new
                    {
                        Id = t.TourId,
                        TourName = t.TourName,
                        TourCategoryId = t.TourCategoryId,
                        Bookings = db.Bookings.Where(b => d.TourDateId == b.TourDateId).Count()                            
                    }).ToList()
                select new ToursAvail2VM
                    {
                         Id = vm.Id,
                         TourName = vm.TourName,
                         TourCategoryId = vm.TourCategoryId,
                         Bookings = vm.Bookings
                    }).ToList();

Upvotes: 1

Related Questions