3

I have a REST-style web application that uses EF code first. I'm using AutoMapper to map my classes to DTO classes for passing across the wire, and (hopefully) back.

When I map from my POCO classes to DTOs, I'm actually starting with an EF proxy object, since the objects I'm dealing with were the result of executing some sort of query against my DataContext. This seems to work fine, however.

When I get back a DTO class as part of a POST request, I can use AutoMapper to map it onto my POCO class, and this works fine too.

However because AutoMapper is just new()-ing the POCO objects rather than using the Create method on the EntitySet, I now have a POCO class rather than the corresponding EF proxy class. This makes it harder for me to add the data to my database etc.

How can I persuade AutoMapper to use EntitySet.Create? Or is there another way to achieve the same result?

Gary McGill
  • 26,400
  • 25
  • 118
  • 202
  • As far as I know AutoMapper it is not extendible with factory methods the way some IoC containers are. It would be an addition that makes perfect sense, but maybe you have to contribute it yourself! – Gert Arnold Aug 06 '12 at 23:03
  • I didn't know far enough: http://stackoverflow.com/questions/2239143/automapper-how-to-map-to-constructor-parameters-instead-of-property-setters and http://stackoverflow.com/questions/11147347/automapper-using-the-wrong-constructor. – Gert Arnold Aug 16 '12 at 20:04
  • @GertArnold: Perfect! You should add that as an answer, and I'll accept it. – Gary McGill Aug 16 '12 at 20:20

3 Answers3

3

Map.CreateMap creates an IMappingExpression object which has a method ConstructUsing that accepts a function that can be used as factory method for new objects. The mapped properties are used to set values. (This can be overriden by ConvertUsing, by the way).

For details, see Automapper - how to map to constructor parameters instead of property setters, AutoMapper using the wrong constructor, or How to use Automapper to construct object without default constructor.

In your case this could be something like:

Mapper.CreateMap<TDto, TPoco>()
    .ConstructUsing((Func<TDto, TPoco>) (c => context.CreateObject<TPoco>()))
Community
  • 1
  • 1
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
1

May be you can do like this,

First create the required object and then use that instance to map the DTO object,

var poco=EntitySet.Create()

Mapper.Map<DTOtype, POCOtype>(dto, poco); 
Jayantha Lal Sirisena
  • 21,216
  • 11
  • 71
  • 92
  • yes, that looks like a good plan in the case of a single object. However, my objects have references to other objects which I'd also want to be converted. (For example, an Order object with several LineItem objects). In that case, I think your suggested solution would work for the Order object, but not the LineItems? – Gary McGill Aug 07 '12 at 08:59
0

Suppose you are accepting POCO object in your post method instead of DTO like

[HttpPost]
public ActionResult Save(Student std)
{
    //do the stuff
}

suppose that Student is EF proxy class but when its bound to the form values using Modelbinder, it creates the new objects not the ones associated with data context. So first thing is, there is no difference if you accept DTO's in post and then convert them to proxy classes or you accept proxy classes in the first place. Second thing is that if object already exist in database and you have just created it using automapper, you can associate with datacontext using attach method. and if its new object you will need to call the Add method to save it in the database.

Muhammad Adeel Zahid
  • 17,474
  • 14
  • 90
  • 155
  • I'm not sure I understand. My DTOs are much simpler than my POCO objects (fewer fields, etc.), so I can't simply switch from DTO to POCO in my ApiController methods - I do need to "map" them. And that's the crux of my question - i.e. how to map them to my POCOs, yet have those POCOs be EF proxies. – Gary McGill Aug 07 '12 at 09:03
  • Well, only thing I say is even if you manage to receive them in controller, they will just be POCOs not EF proxies. you'll have to attach them with EF data context using its methods like attach (if entity already in db) or add (if entity is new). – Muhammad Adeel Zahid Aug 07 '12 at 09:35
  • I just gave an example, its not recommended to use db entities in controller method signatures. – Muhammad Adeel Zahid Aug 07 '12 at 09:36
  • "even if you manage to receive them in controller, they will just be POCOs not EF proxies" -- that's the point of my question! I'm trying to create EF proxies from my DTOs, either directly or via the POCOs. – Gary McGill Aug 07 '12 at 11:23