Cleanest Way To Map Entity To DTO With Linq Select?

前端 未结 4 1975
梦如初夏
梦如初夏 2020-12-13 19:45

I\'ve been trying to come up with a clean and reusable way to map entities to their DTOs. Here is an example of what I\'ve come up with and where I\'m stuck.

相关标签:
4条回答
  • 2020-12-13 20:33

    You could either use AutoMapper or write extension methods like these:

    public static class PersonMapper
    {
        public static PersonDTO ConvertToDTO(this Person person)
        {
            return new PersonDTO { ID = person.ID, Name = person.Name, Address = person.Address.ConvertToDTO() };
        }
    
        public static IEnumerable<PersonDTO> ConvertToDTO(this IEnumerable<Person> people)
        {
            return people.Select(person => person.ConvertToDTO());
        }
    }
    
    public static class AddressMapper
    {
        public static AddressDTO ConvertToDTO(this Address address)
        {
            return new AddressDTO { ID = address.ID, City = address.City };
        }
    
        public static IEnumerable<AddressDTO> ConvertToDTO(this IEnumerable<Address> addresses)
        {
            return addresses.Select(address => address.ConvertToDTO());
        }
    }
    

    You could then map a Person object to a PersonDTO object like this:

    public class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person { ID = 1, Name = "John", Address = new Address { ID = 1, City = "New Jersey" } };
            PersonDTO personDTO = person.ConvertToDTO();
            Console.WriteLine(personDTO.Name);
        }
    }
    
    0 讨论(0)
  • 2020-12-13 20:35

    Just use AutoMapper.

    Example:

    Mapper.CreateMap<Address, AddressDTO>();
    Mapper.CreateMap<Person, PersonDTO>();
    

    Your query will execute when the mapping is performed but if there are fields in the entity that you're not interested use Project().To<> which is available both for NHibernate and EntityFramework. It will effectively do a select on the fields specified in the mapping configurations.

    0 讨论(0)
  • 2020-12-13 20:35

    If you want to create mappings manually then you can use Select on the collection in the following way:

    Some test data:

        var persons = new List<Person>
        {
            new Person() {ID = 1, Name = "name1", Address = new Address() {ID = 1, City = "city1"}},
            new Person() {ID = 2, Name = "name2", Address = new Address() {ID = 2, City = "city2"}},
            new Person() {ID = 3, Name = "name3", Address = new Address() {ID = 1, City = "city1"}}
        };
    

    Mapping methods:

        public static PersonDTO ToPersonDTOMap(Person person)
        {
            return new PersonDTO()
            {
                ID = person.ID,
                Name = person.Name,
                Address = ToAddressDTOMap(person.Address)
            };
        }
    
        public static AddressDTO ToAddressDTOMap(Address address)
        {
            return new AddressDTO()
            {
                ID = address.ID,
                City = address.City
            };
        }
    

    Actual usage:

    var personsDTO = persons.Select(x => ToPersonDTOMap(x)).ToList();
    

    Keep in mind that if this was a real query is would not get executed as long as it was IQueryable, it would be executed once you materialize it (using ToList() for example).

    However, I would consider using some framework which could do it (the mappings) for you automatically (if your mapping are as simple as provided example(.

    0 讨论(0)
  • 2020-12-13 20:39

    Automapper is the best way .

    For me, I use this for simple objects only, but I don't recommend it

      public static class ObjectMapper
    {
        public static T Map<T>(object objfrom, T objto)
        {
            var ToProperties = objto.GetType().GetProperties();
            var FromProperties = objfrom.GetType().GetProperties();
    
            ToProperties.ToList().ForEach(o =>
                {
                    var fromp = FromProperties.FirstOrDefault(x => x.Name == o.Name && x.PropertyType == o.PropertyType);
                    if (fromp != null)
                    {
                        o.SetValue(objto, fromp.GetValue(objfrom));
                    }
                });
    
            return objto;
        }
    }
    

    And I call it like that wherever I want

       var myDTO= ObjectMapper.Map(MyObject, new MyObjectDTO());
    
    0 讨论(0)
提交回复
热议问题