Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing DTOs and mapping in large .NET project

Tags:

.net

mapping

dto

My team and I are building a large .NET WinForms applications. The application uses various "Services" to get data to and from our database. Each "service" lives in its own solution, and handles a specific type of data. So, for example, our "ContactsService" manages retrieving / saving contacts to our database.

Typically, we have been building DTOs for each service. So, we might have a "ContactDTO" that has simple string properties for each piece of data on the contact. Now, we also have a business layer "Contact" class that has the exact same properties, and perhaps a few extra methods with some business logic. On top of that, the "ContactsService" has its own Contact class, which is hydrated from the ContactDTO.

It has become a huge pain to manage all of our DTOs and mapping. Currently, sending a contact to be stored in the database looks like this:

  • Map client Contact to ContactDTO
  • Map ContactDTO to service Contact
  • Save Contact
  • Map service Contact to ContactDTO
  • Map ContactDTO to client Contact

This just feels crappy. If we add a property to our client Contact class, we have to add the property and mappings in 3-4 places.

What are we doing wrong and how can we make our lives easier? Would it be simpler to use something like Json.NET and have JSON DTOs? We checked out AutoMapper, but some team members thought it was too complicated.

like image 944
TaylorOtwell Avatar asked Jul 06 '11 18:07

TaylorOtwell


1 Answers

I've run into this a lot, but in my case I've chosen to accept it because the decision to use DTOs was an intentional one - I want my service, client, proxy, and contract assemblies to be cleanly separated.

When using WCF, the layout I prefer is something like this (using your Contact example):

  • Client assembly
    • Contact (has client-y characteristics)
  • Shared Contracts assembly
    • Contact (the agreed-upon common DTO)
  • Proxy assembly
    • Uses the Contact from the shared Contracts assembly
  • Service assembly
    • Contact (has service-y business logic characteristics, e.g. this may be the type exposed by an ORM layer like Entity Framework)

I'm now sharing the contracts between the service and the client. If I ever need to version them independently, then I can just make a copy of the shared Contracts assembly and re-target the Proxy assembly to use the copy, and then modify the two Contracts assemblies independently. But in most cases that I've worked in, I own both the client and the service, so it's convenient to share the Contracts assembly between the two.

That's the only optimization that I can think of when you make the architectural decision to isolate your components with DTOs, at least without using code generation tools (I don't know of any good ones, but haven't had to look into them).

Edit: When not using WCF, you obviously won't need the 'Proxy' assembly.

like image 90
Lars Kemmann Avatar answered Sep 28 '22 14:09

Lars Kemmann