Mapping entities to DTOs without duplicated code

c# dto entity-framework entity-framework-6

Question

I'm trying to get my head around this issue where I am using the Entity Framework (6) in an N-tier application. Since data from the repository (which contains all communication with the database) should be used in a higher tier (the UI, services etc), I need to map it to DTOs.

In the database, there's quite a few many-to-many relationships going on, so the datastructure can/will get complex somewhere along the line of the applications lifetime. What I stumbled upon is, that I am repeating the exact same code when writing the repository methods. An example of this is my FirmRepository which contains a GetAll() method and GetById(int firmId) method.

In the GetById(int firmId) method, I have the following code (incomplete since there's a lot more relations that needs to be mapped to DTOs):

public DTO.Firm GetById(int id)
    {
        // Return result
        var result = new DTO.Firm();

        try
        {
            // Database connection
            using (var ctx = new MyEntities())
            {
                // Get the firm from the database 
                var firm = (from f in ctx.Firms
                            where f.ID == id
                            select f).FirstOrDefault();

                // If a firm was found, start mapping to DTO object
                if (firm != null)
                {
                    result.Address = firm.Address;
                    result.Address2 = firm.Address2;
                    result.VAT = firm.VAT;
                    result.Email = firm.Email;

                    // Map Zipcode and City
                    result.City = new DTO.City()
                    {
                        CityName = firm.City.City1,
                        ZipCode = firm.City.ZipCode
                    };

                    // Map ISO code and country
                    result.Country = new DTO.Country()
                    {
                        CountryName = firm.Country.Country1,
                        ISO = firm.Country.ISO
                    };

                    // Check if this firm has any exclusive parameters
                    if (firm.ExclusiveParameterType_Product_Firm.Any())
                    {
                        var exclusiveParamsList = new List<DTO.ExclusiveParameterType>();

                        // Map Exclusive parameter types
                        foreach (var param in firm.ExclusiveParameterType_Product_Firm)
                        {
                            // Check if the exclusive parameter type isn't null before proceeding
                            if (param.ExclusiveParameterType != null)
                            {
                                // Create a new exclusive parameter type DTO
                                var exclusiveParameter = new DTO.ExclusiveParameterType()
                                {
                                    ID = param.ExclusiveParameterType.ID,
                                    Description = param.ExclusiveParameterType.Description,
                                    Name = param.ExclusiveParameterType.Name
                                };

                                // Add the new DTO to the list
                                exclusiveParamsList.Add(exclusiveParameter);
                            }
                        }

                        // A lot more objects to map....

                        // Set the list on the result object
                        result.ExclusiveParameterTypes = exclusiveParamsList;
                    }
                }
            }

            // Return DTO
            return result;
        }
        catch (Exception e)
        {
            // Log exception
            Logging.Instance.Error(e);

            // Simply return null
            return null;
        }
    }

This is just one method. The GetAll() method will then have the exact same mapping logic which results in duplicated code. Also, when more methods gets added, i.e. a Find or Search method, the same mapping needs to be copied again. This is, of course, not ideal.

I have read a lot about the famous AutoMapper framework that can map entites to/from DTOs, but since I have these many-to-many relations it quickly feels bloated with AutoMapper config code. I've also read this article, which make sense in my eyes: http://rogeralsing.com/2013/12/01/why-mapping-dtos-to-entities-using-automapper-and-entityframework-is-horrible/

Is there any other way of doing this without copy/pasting the same code over and over again?

Thanks in advance!

1
2
9/30/2014 5:20:56 PM

Popular Answer

You can make an extension method on Entity firm (DB.Firm) like this,

public static class Extensions
    {
        public static DTO.Firm ToDto(this DB.Firm firm)
        {
           var result = new DTO.Firm();
           result.Address = firm.Address;
           result.Address2 = firm.Address2;
           //...

           return result;    
        }
    }

Then you can convert DB.Firm object anywhere in your code like firm.ToDto();

2
10/1/2014 4:21:09 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow