This topic describes considerations that are specific to developing DTO layers with the Service Wizard.
This topic applies to WCF Plain, Atom and RESTful Collection Services only.
Suppose that you are designing a distributed application. The question is: how would you move data to and from the presentation layer? Ideally, you create objects that are used to pass data from the presentation layer to the service layer, and back. These container objects take the name of Data Transfer Objects (DTOs). A DTO is nothing more than a container class that exposes properties but no methods. A data transfer object (DTO) holds all data that is required for the remote call. Your remote method will accept the DTO as a parameter and return a DTO to the client. After the calling application receives the DTO and stores it as a local object, the application can make a series of individual procedure calls to the DTO without incurring the overhead of remote calls. For more information about DTOs, read here.
The DTO layer itself is designed to be highly decoupled, so that the generated assemblers, DTOs, repositories and even services can be easily used outside of the generated service. Every aspect of the DTO layer can be switched with an extended or even completely new implementation as everything is referenced by interfaces.
The next several sections make an overview of the different classes generated for the DTO layer.
An implementation of the Assembler pattern that can convert back and forth from DTOs to Telerik Data Access entities. The key characteristic of Assembler is that the DTO and the domain object do not depend on each other. This decouples the two objects. The downside is that Assembler depends on both the DTO and the domain object. Any change to these classes may result in having to change the Assembler class.
Note that navigational properties are not turned on by default. The Telerik Data Access Add Service Wizard provides code that can populate collections on entities and it is generated in the assemblers. However it is not plugged in and not executed by default. If you want to, you can plug it by extending the class through a partial. For example, see How to Handle Relationships in WCF Plain Services.
An implementation of the Repository pattern that enables access to the data shaped by your decision in step 3 of the wizard. Repositories are used for retrieving, adding and deleting objects from the database and in order to do so they have a single dependency on the UnitOfWork implementation. These operations are mostly implemented in a generic base class. Note that the repositories do not expose a SaveChanges operation. The Repository pattern has the following advantages:
- Isolates the data layer to support unit testing.
- Allows you to access the data source from many locations by applying centrally managed, consistent access rules and logic.
- Allows you to implement and centralize a caching strategy for the data source.
For more information about the Repository pattern, read here.
An interface that is implemented by the customer context class deriving from OpenAccessContext. It exposes the SaveChanges and ClearChanges methods. For more information about the UnitOfWork pattern, read here.
A service class is implemented for each entity, it exposes CRUD operations using DTO objects to the outside. It is the glue that holds together both the Assemblers and Repositories and is the perfect place for a customer to add domain logic to this DTO layer.
The actual implementation of all DTO classes.
All of the DTO classes implement an interface that exposes a single string property called DtoKey, which is a string representation of the object’s identity. The KeyUtility is a singleton used in both the Assemblers and Service classes. It is used for reading from and to the DtoKey string property into a Telerik Data Access ObjectKey that can be used to retrieve the desired objects.