Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Data Transfer Object Design Pattern in C#

4.82/5 (22 votes)
6 Nov 2015CPOL3 min read 265.3K  
In this article we will explain about Data Transfer Object Design pattern in C#

Table of Contents

Introduction and Definition

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.

C#
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.

C#
class CustomerDTO
{
        public string CustomerName { get; set; }
}

So in this article, let us try to understand in what kind of scenarios DTOs are used.

Scenario 1 :- Improve performance

Consider the below scenario. We have a customer business class and a product business class.

C#
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; 
            }
        }
}
C#
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.

C#
DataAccessLayer dal = new DataAccessLayer();
//Call 1:-  get Customer data
CustomerBO cust = dal.getCustomer(1001);

//Call 2:-  get Products for the customer
ProductsBO prod = dal.getProduct(100);

So to achieve the same, we can create a unified simple class which has properties from both the classes.

C#
class CustomerProductDTO
{
  // Customer properties
        public string CustomerName { get; set; }
   // Product properties
        public string ProductName { get; set; }
        public double ProductCost { get; set; }
}

You can now get both Customer and Product data in one go.

C#
//Only one call
CustomerProductDTO cust = dal.getCustomer(1001);

Proxy objects in WCF and Web services are good candidates for data transfer objects to improve performance.

Scenario 2:- Flatten object hierarchy

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.

C#
class CustomerBO
{
 // Customer properties removed for reading clarity
public List<addressbo> Addresses { get; set; }
}
C#
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.

C#
class CustomerDTO
{
public string CustomerName { get; set; }
public string ProductName { get; set; }
public double ProductCost { get; set; }
}

Scenario 3:- Exclude properties

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.

C#
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.

C#
class CustomerDTO
{
        public string CustomerName { get; set; }
}

Difference between DTO and Business objects

  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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)