Table of Contents
DTO (Data Transfer objects) is a data container for moving data between layers. They are also termed as transfer objects. DTO is only used to pass data and does not contain any business logic. They only have simple setters and getters.
For example, below is an Entity
class or a business class. You can see that it has business logic in the setters.
class CustomerBO
{
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
A data transfer object of the above Customer
entity class would look something as shown below. It will only have setters and getters that means only data and no business logic.
class CustomerDTO
{
public string CustomerName { get; set; }
}
So in this article, let us try to understand in what kind of scenarios DTOs are used.
Consider the below scenario. We have a customer business class and a product business class.
class CustomerBO
{
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
public class ProductsBO
{
private string _ProductName;
public string ProductName
{
get { return _ProductName; }
set
{
if (value.Length == 0)
{
throw new Exception("Product Name is required");
}
_ProductName = value;
}
}
public double ProductCost { get; set; }
}
Assume there is a remote client which is making calls to get Customer
data and the Products
they bought. Now the client has to make two calls, one to get Customer
data and the other to get Products
data. Now that is quiet inefficient. It would be great if we can get data in one call.
DataAccessLayer dal = new DataAccessLayer();
CustomerBO cust = dal.getCustomer(1001);
ProductsBO prod = dal.getProduct(100);
So to achieve the same, we can create a unified simple class which has properties from both the classes.
class CustomerProductDTO
{
public string CustomerName { get; set; }
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
You can now get both Customer
and Product
data in one go.
CustomerProductDTO cust = dal.getCustomer(1001);
Proxy objects in WCF and Web services are good candidates for data transfer objects to improve performance.
The second scenario where I end up using DTO objects is for flattening the object hierarchy for easy data transfer.
For example, you have a customer business class which has one to many relationships with an address class. But now let us say we want to write this whole data to a CSV file or transfer it across layers. In those scenarios, a flattened denormalized structure makes things easier.
So you have a customer
class which has one to many relationship with address
objects. It also has business rules in it.
class CustomerBO
{
public List<addressbo> Addresses { get; set; }
}
class AddressBO
{
private string _Address1;
public string Address1
{
get { return _Address1; }
set
{
if (value.Length == 0)
{
throw new Exception("Address is required");
}
_Address1 = value;
}
}
}
To create a DTO of the above customer
and address
class, we can just merge both the properties of the classes into one class and exclude the business logic.
class CustomerDTO
{
public string CustomerName { get; set; }
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
Because DTO is completely detached from the main business object, you have the liberty to remove certain fields which you do not want to transfer to the other layers. For example, below is a simple customer business object class which has two properties called as “IsAdmin
” and “CustomerName
”.
When you pass this business object to the UI layer, you do not wish to transfer the “IsAdmin
” value to the UI.
class CustomerBO
{
private bool _IsAdmin;
public string IsAdmin
{
get { return _IsAdmin; }
}
private string _CustomerName;
public string CustomerName
{
get { return _CustomerName; }
set
{
if (value.Length == 0)
{
throw new Exception("Customer name is required");
}
_CustomerName = value;
}
}
}
So you can create a DTO which just has the “CustomerName
” property.
class CustomerDTO
{
public string CustomerName { get; set; }
}
| Business objects | DTO |
Data | Yes | Yes |
Business logic | Yes | No |
Structure | Normalized | Normalized or Denormalized |
If we can mathematically summarize:
Business object = Data + Logic
DTO = Data
In case you want to learn design pattern, I would suggest to learn design pattern with a project. Do not learn each design pattern individually. Because when design patterns are used in project, they overlap with each other and such kind of experience can only be felt by doing an actual project and implementing design patterns on demand and naturally.
For Further reading do watch the below interview preparation videos and step by step video series.