2

I haveBusinessLayer, DTO library,DataService, EntityModel(wher EDMX sits), DTO library refers to both business and data layer. I am trying to implement automapper in data layer, want to map entity object to DTO object and return DTO from the dataService library.

Currently am doing this way

public class DataService
{
    private MapperConfiguration config;
    public DataService()
    {
        IMapper _Mapper = config.CreateMapper(); 
    }

    public List<Dto.StudentDto> Get()
    {
        using(var context = new DbContext().GetContext())
        {
            var studentList =  context.Students.ToList();
            config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Db.Student, Dto.StudentDto>();
            });
            var returnDto = Mapper.Map<List<Db.Student>, List<Dto.StudentDto>>(studentList);
            return returnDto;
        }
    }
}

How can I move all the mappings to one class and automapper should initialize automatically when call to dataserive is made?

PRK
  • 177
  • 1
  • 4
  • 15

2 Answers2

8

Is it good practice to use AutoMapper in data layer?

Yes.

How can I move all the mappings to one class and automapper should initialize automatically when call to dataserive is made?

You could just create a static class that creates the mappings once:

public static class MyMapper
{
    private static bool _isInitialized;
    public static Initialize()
    {
        if (!_isInitialized)
        {
            Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<Db.Student, Dto.StudentDto>();
            });
            _isInitialized = true;
        }
    }
}

Make sure that you use this class in your data service:

public class DataService
{
    public DataService()
    {
        MyMapper.Initialize();
    }

    public List<Dto.StudentDto> GetStudent(int id)
    {
        using (var context = new DbContext().GetContext())
        {
            var student = context.Students.FirstOrDefault(x => x.Id == id)
            var returnDto = Mapper.Map<List<Dto.StudentDto>>(student);
            return returnDto;
        }
    }
}

Dependending on how you actually host the DAL, you might be able to call the Initialize() method of your custom mapper class from the Main() method of an executable or from somewhere else than the constructor of your DataService class.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • How to call this public static class MyMapper, class from the startup project, we are using prism for wpf development. What if i call the mapper.Initialize() from the every dataservice class? – PRK Jun 26 '17 at 17:04
  • You should only call it once per AppDomain. If you are using Prism, a good place to do this would be in your Bootstrapper class. – mm8 Jun 26 '17 at 17:11
  • If want to initialize in Bootstrapper, then I have to this DataService project reference to UI (dont want to add DataProject to UI), How to initialize from bootstrapper – PRK Jun 26 '17 at 17:16
  • Of course you need to add a reference to the assembly/project where the DTO classes are defined from the UI project where the Bootstrapper class is defined. This is not an issue. In fact, you are required to do this if the DAL lives in the same process as the client application. – mm8 Jun 26 '17 at 17:18
  • Thanks but, here our requirement is not to add any BL or DAL reference to UI project, Everything has to be done ViewModels library or Infrastructure project. What is the issue, if i call AutoMapper from the constructor of every class? – PRK Jun 26 '17 at 17:25
  • Then you obviously cannot initialize the AutoMapper in your UI project, that's for sure. But you could just add a boolean flag to the static Initialize method of your MyMapper class and make sure that you only map the types *once* no matter how many times the method gets called. – mm8 Jun 26 '17 at 17:32
  • Please see my edited answer. Using the boolean flag _isInitialized, you can call the Initialize() method how many times you want from the constructor of your DataService object(s). The type mapppings will still only be created once. So then there should be no issue :) – mm8 Jun 26 '17 at 17:37
1

Use AutoMapper.Mapper.CreateMap on OnAppInitialize. You can do the implementation of course in an own static class for better style.

There is really no more magic in this - because you only have to register (CreateMap) the mappings one time.

initialize automatically when call to dataserive is made?

You can of course register it too in the constructor.

Here you can take a look at another sample - how to use register in one or two of many extended ways.

In the end AutoMapper should make your life easier and not harder. In my opinion the best way is to register everything at one point - when starting the application.

But you also can do it on demand like seperating each CreateMapin the constructor.

Both ways - just make sure you just call it once.

Peter
  • 1,655
  • 22
  • 44
  • if possible can you share some example, is it good practice to use AutoMapper in data layer? – PRK Jun 25 '17 at 20:03
  • I just used it within `ASP.NET` and registered it there in a kind of startup method. This makes much sense there and i think same with `WPF`, because u just want to do it one time anyway. – Peter Jun 25 '17 at 20:50
  • As per the eg, the party is data entity class, to call the RegisterMappings() method and resolve data entity, I have to add data service library project reference to UI project then? I want create this class "AutoMapperConfiguration" in data layer. I can't add data service reference to UI project – PRK Jun 25 '17 at 21:19
  • Edited again - just make sure you dont CreateMap in the getter over and over and over and over again ... – Peter Jun 25 '17 at 21:43