0

I have two types. One in the business layer:

namespace Business
{
    public class Car
    {

        private int _id;
        private string _make;
        private string _model;

        public int id
        {
            get { return _id; }
            set { _id = value; }
        }

        public string make
        {
            get { return _make; }
            set { _make = value; }
        }

        public string model
        {
            get { return _model; }
            set { _model = value; }
        }

    }

}

and the other in the Data layer (Entity Framework):

namespace Data
{
    using System;
    using System.Collections.Generic;

    public partial class Car
    {
        public Car()
        {
            this.facttables = new HashSet<facttable>();
        }

        public int id { get; set; }
        public string make { get; set; }
        public string model { get; set; }

        public virtual ICollection<facttable> facttables { get; set; }
    }
}

Here is the code I get from the service layer:

    namespace Data
{
    public class VehicleDAO : IVehicleDAO
    {

        private static readonly ILog log = LogManager.GetLogger(typeof(VehicleDAO));

        MapperConfiguration config;

        public VehicleDAO ()
        {
            Mapper.Initialize(cfg => cfg.CreateMap<Business.Car, Data.Car>());
            config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Business.Car, Data.Car>()
                    .ForMember(dto => dto.facttables, opt => opt.Ignore());
                    //.ForMember(d => d.id, opt => opt.MapFrom(c => c.id))
                    //.ForMember(d => d.make, opt => opt.MapFrom(c => c.make))
                    //.ForMember(d => d.model, opt => opt.MapFrom(c => c.model));
            });
            config.AssertConfigurationIsValid();
        }

        public Data.Car Select(int id)
        {
            Data.Car car;
            using (VehicleEntities VehicleDatabase = new VehicleEntities())
            {
                car = VehicleDatabase.Cars.Where(c => c.id == id).ToList().Single();
                Business.Car cars = AutoMapper.Mapper.Map<Business.Car>(car);
            }
            return car;
        }

The exception is: {"Missing type map configuration or unsupported mapping.\r\n\r\nMapping types:\r\nCar_70BD8401A87DAAD8F5F0EC35BCAE5C9E6EE2D6CB5A1AFCE296B313D8AD87D2E9 -> Car\r\nSystem.Data.Entity.DynamicProxies.Car_70BD8401A87DAAD8F5F0EC35BCAE5C9E6EE2D6CB5A1AFCE296B313D8AD87D2E9 -> Business.Car"}. What is wrong? I have marked the line that causes the exception (third from last line).

w0051977
  • 15,099
  • 32
  • 152
  • 329
  • `cfg.CreateMap().ForMember(c => c.facttables, option => option.Ignore()).ReverseMap()` ? I guess that might only work with simple maps. Remember you have to define your mapping in both directions to get a map in both directions (i always forget which is source and which is destination without pulling up the docs) – Kritner Jul 14 '16 at 15:48
  • `.ReverseMap()` does indeed only work for simple mappings. However I think part of the problem here is that the mapping is defined between `Business.Car` and `Data.Car` but as the error message says, that actual type is `System.Data.Entity.DynamicProxies.Car_70BD8401A87DAAD8F5F0EC35BCAE5C9E6EE2D6CB5A1AFCE296B313D8AD87D2E9` which is an Entity Framework proxy. Unless AutoMapper has got cleverer about handing this, it won't work as it's a different type, and you have to disconnect the entity from EF by projection before you map it. – stuartd Jul 14 '16 at 15:58
  • @stuartd, thanks. How do you "disconnect the entity from EF projection"? – w0051977 Jul 14 '16 at 16:49
  • @stuartd, could you provide some code? I have spent hours looking at this and I have no idea what the problem is. – w0051977 Jul 15 '16 at 13:46
  • Have a look at [Automapper, MapFrom and EF dynamic proxies](http://stackoverflow.com/questions/25507228/automapper-mapfrom-and-ef-dynamic-proxies) and specifically [AutoMapper's IQueryable extensions](https://github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions) – stuartd Jul 15 '16 at 13:51
  • @stuartd, your links talk about eager loading and how to optimise LINQ queries. I am not sure how they help. – w0051977 Jul 15 '16 at 14:04
  • @stuartd, thanks, however I still get the same error with your code. Could you take a look at the code in the question again which shows where I am up (the changes I have made). – w0051977 Jul 15 '16 at 14:14
  • @stuartd, be what? – w0051977 Jul 15 '16 at 14:17
  • @stuartd, the code is in the question. I have spent hours looking into this. It would be so much simpler to just write the mapping code manually. Automapper seems to make it much more complex than it needs to be. – w0051977 Jul 15 '16 at 14:22
  • @stuartd, are you able to see whazt the problem is from the code. What more information do you need? Thanks. – w0051977 Jul 15 '16 at 14:29
  • Give this a go **instead of** the call to `Map()`: `VehicleDatabase.Cars.Where(c => c.id == id).ProjectTo().ToList().Single();` – stuartd Jul 15 '16 at 14:31
  • I tried that earlier after reading your link. There is a compilation error: "system.linq.iqueryable does not have a definition for ProjectTo" – w0051977 Jul 15 '16 at 14:37
  • Well, you would need to add the namespace `AutoMapper.QueryableExtensions` to the file – stuartd Jul 15 '16 at 14:51
  • @stuartd,same problem. Can you provide an answer with a code frangment? – w0051977 Jul 15 '16 at 15:21
  • I can't give an answer as it seems I don't know the answer. Without a repro, I can't help any more, sorry, and I have my own work to do.. – stuartd Jul 15 '16 at 15:24
  • @stuartd, I found my answer here: http://codewithstyle.info/solving-entity-framework-performance-issues-automapper/. Thank you for your help. It is now working. – w0051977 Jul 15 '16 at 16:14
  • @w0051977 glad you got it working, just in time for the weekend :) – stuartd Jul 15 '16 at 16:33

1 Answers1

0

Automapper only maps in the direction you created the mapping in. CreateMap<Business.Car, Data.Car> creates a mapping from Business.Car to Data.Car. It looks like you are trying to map from Data.Car to Business.Car, which means you need to CreateMap<Data.Car, Business.Car>

Mapper.Initialize(cfg => cfg.CreateMap<Data.Car, Business.Car>());
config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Data.Car, Business.Car>();
});
config.AssertConfigurationIsValid();
Ryan Fleming
  • 189
  • 7
  • Edited to include what I meant. I think you just have your type parameters backwards. – Ryan Fleming Jul 14 '16 at 16:03
  • I still see the same error: Missing type map configuration or unsupported mapping.\r\n\r\nMapping types:\r\nCar_70BD8401A87DAAD8F5F0EC35BCAE5C9E6EE2D6CB5A1AFCE296B313D8AD87D2E9 -> Car\r\nSystem.Data.Entity.DynamicProxies.Car_70BD8401A87DAAD8F5F0EC35BCAE5C9E6EE2D6CB5A1AFCE296B313D8AD87D2E9 -> Business.Car"} – w0051977 Jul 14 '16 at 16:50
  • Instead of AutoMapper.Mapper.Map(DataCar), have you tried used AutoMapper.Mapper.Map(DataCar)? That should force auto-mapper to use the mapping you created. The single parameter Map you are using gets its type from the object, which is the EF object proxy. – Ryan Fleming Jul 14 '16 at 16:56