Search code examples
c#entity-frameworkpocodto3-tier

Placement of DTO / POCO in a three tier project


I've been in the process of re-writing the back-end for a web site and have been moving it towards a three-tiered architecture.

My intention is to structure it so:

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

My issue is with the placement of the DTO's within this structure. I'll need to use DTO's to move data between the business layer and the WCF service and from the WCF service to the consuming web site.

During my research on here I've read some excellent discussions though I've been left scratching my head a bit:

  • Davide Piras makes some great points in this post and if I were to follow this design then I'd declare interfaces for the POCOs in a separate project. These would then be implemented by tiers (1) and (2). Whilst I like the use of interfaces it does seem like I'd be making more work for myself by declaring POCOs in (1) and (2) and then copying their data back and forth using something like AutoMapper.

  • This post uses a system where a business objects project is created which would be referenced by all tiers. This seems to be simplier than the other solution and seems to lead me to a solution that would be

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

^               ^                       ^
|               |                       |
[ -- Business Objects Referenced here --]

My question is this: is there a code smell from sharing the business objects across three layers of the solution or are the two methods I've listed above just two different ways of cracking the same nut?


Solution

  • Let's think of your UI (website) and service (WCF + BL + DAL) as two distinct entities.

    • If you have 100% control over both, you should choose approach #2 since it will avoid translation between WCF proxy objects and your business objects in the UI layer.

    • Else, you are better off with approach #1 since one of the entities is kind of a 'black box' and is subject to change by external stakeholders. So, it's safer to maintain an internal set of business objects. This will need translation between your business objects and the WCF proxy objects (through Extension methods or a translator framework).

    Now, not exactly sure of your UI layer complexity or its implementation (MVC, WebForms, etc.), so you may or may not need View specific objects (lighter for data-binding, faster to serialize to JSON, etc.), let's call this object as the Model.

    • If you don't need a distinct UI specific Model, suggest to mark your business objects as DataContract (in the context of WCF) and use them across layers. Don't forget to explicitly mark entities as Serializable if you are invoking WCF via the web ($.ajax).

    • Else, use DataContract in the service and a translator to convert DataContract to Model in the UI layer. A Service Adapter is a good fit here - it sits in the UI layer and is responsible for consuming the WCF service and translating between DataContract and Model. You may use a Service Proxy in the UI layer, which is a wrapper over your WCF service and is consumable over the web.

    Lastly, aren't you are missing a reference to the Business Objects in your Data Layer? I believe you will populate your Business Objects from the data-store in the Data Layer itself.