Search code examples
c#linqrepositoryautomappergeneric-programming

How to use Automapper inside GenericRepository to Map Entities to DTO?


I want to add a method to my Repository that maps the given Generic type to a DTO. Assume that these are my Entity and DTO:

public class User : BaseEntity
{
    public string firstName { get; set; }
    public string lastName { get; set; }

    List<UserOperation> operations { get; set; }
}

public class Operation : BaseEntity
{
    public string src { get; set; }
    public string title { get; set; }
}

public class UserOperation : BaseEntity
{
    public int sortOrder { get; set; }

    public Int64 userId { get; set; }
    [JsonIgnore]
    public virtual User user { get; set; }

    public Int64 operationId { get; set; }
    [JsonIgnore]
    public virtual Operation operation { get; set; }
}

And I want to have a method like this in GenericRepository:

public interface IGenericRepository<T, Key>
{
PagedResult<U> getAllGrid<U>(IQueryable<T> query, SearchOption option) where U : class;
}

public class GenericRepository<T, Key> : IGenericRepository<T, Key> where T : BaseEntity
{
    public PagedResult<U> getAllGrid<U>(IQueryable<T> query, SearchOption option) where U : class
            {
                    Mapper.CreateMap<T, U>();

                    var totalRecordsCount = query.Count();

                    if (totalRecordsCount != 0)
                    {
                        List<U> mappedEntities = new List<U>();
                        foreach (T item in query.OrderBy(option.orderBy + " " + option.orderByType).Skip(option.start * option.size).Take(option.size))
                        {
                            mappedEntities.Add(Mapper.Map<T, U>(item));
                        }

                        return new PagedResult<U>()
                        {
                            Result = true,
                            Records = JsonConvert.SerializeObject(mappedEntities)
                        };
                    }
                    else
                        return new PagedResult<U>() { Result = true, MainRecords = null };
            }
}

public class UserOperationRepository : GenericRepository<UserOperation, Int64>, IUserOperationRepository
{
    public UserOperationRepository()
    {
        base.context = new AppContext();
    }
    public PagedResult<UserOperationDTO> getAllGrid(long userId, SearchOption option)
    {
        var query = base.context.Set<UserOperation>().AsQueryable();

        return base.getAllGrid<UserOperationDTO>(query, option);
     }
 }

I'm new to automapper and GenericRepository.


Solution

  • AutoMapper supports projection - you don't need to call Mapper.Map:

    var mappedEntities = query
        .OrderBy(option.orderBy + " " + option.orderByType)
        .Skip(option.start * option.size)
        .Take(option.size)
        .Project().To<U>()
        .ToList();
    

    I would also gather all your CreateMap's in one place - CreateMap is expensive and is only intended to be called once per AppDomain.