Pages

Saturday, August 15, 2009

Using Custom Entities in ASP.NET Applications – Part 3



This is the third and final part of my short series on using custom entities in asp.net applications. In this part, we will look at some coding technique commonly used to program around custom entities and data transfer objects. For the sake of brevity, I will not go into the coding details rather focus on the architectural issues. So let’s get started.


Using Custom Entities and DTOs

Many of the sample applications show how to use Custom Entities (and DTOs). In addition to the standard UI, BLL and DAL Layer, the usual design is to have a fourth layer (usually known as Model Layer) consisting of Data Transfer Objects. The DTOs in the model layer is used for transfer of data betweent the three layers. Usually when a user makes a request, it flows from the UI to the BLL and finally to the DAL. In response, the DAL populates one or more DTOs and sends it back to the BLL. The BLL then sends the data back to the UI. Pay close attention to this last statement which is highlighted. To me, this is where we can employ different coding techniques and this decision is left to the developer. Let me explain these techniques in the following sections with examples.


Using DTOs - Only

In this technique, only DTOs are used between all the layers for transfer of data. The BLL returns the same DTOs received from the DAL to the UI. The UI binds to one or more instances of DTOs. Listing 1 shows this technique:


Listing 1


// Model Layer
using System;

public class EmployeeDTO
{
// properties
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Designation { get; set; }
public int Age { get; set; }

// constructor
public EmployeeDTO () {}

// constructor
public EmployeeDTO (int employeeId, string name, string address, string designation, int age)
{
this.EmployeeID = employeeId;
this.Name = name;
this.Address = address;
this.Designation = designation;
this.Age = age;
}
}


// Business Logic Layer
using System;

public class Employee
{
public Employee () {}

public IList GetAllEmployees ()
{
return EmployeeDAL.GetAllEmployees ();
}

public EmployeeDTO GetEmployeeById (int employeeId)
{
return EmployeeDAL.GetEmployeeById (employeeId);
}

public int Save (EmployeeDTO employee)
{
return EmployeeDAL.Save (employee);
}

// Validation…

// Business Rules…

}


The Emloyee entity in the BLL has a corresponding data transfer object (EmployeeDTO) in the Model Layer. The Employee entity has different CRUD methods. These methods accept and return one or more instances of type EmployeeDTO. This technique is shown in figure 1.

         DTO                   DTO
UI <----------> BLL <-----------> DAL
Fig 1


There is nothing wrong in using DTOs throughout the application. But to me, this has a few shortcomings. First of all, this technique breaks the basic principle of OO programming, Encapsulation. Encapsulation states that both the state and behavior are held within the object. The object itself is responsible for managing its state and behavior. The state or behavior cannot be separated from the object. In the above code, the Employee class (residing in the BLL) does not define any state. It instead relies on the EmployeeDTO (Model Layer) to handle its state. This shows that the object is not in charge of its state and hence clearly breaks the principle of encapsulation.

Second, custom entities (defined in the BLL) have association with each other. These associations are defined by the help of their properties (primary keys). If they lack any property (as in the above code) then how do we define an association? I don’t see a point in defining associations in the Model Layer between data transfer objects (which lack any behavior as well).

Data Transfer Objects lack behavior yet they are not without advantage. Since they only consist of properties, they are light weight objects used to send data across subsystems and hence help improve the throughput of the system.



Using DTOs in parallel to Custom Entities

In this case, DTOs are limited between the BLL and DAL for transfer of data. However; the UI binds to custom entities instead of DTOs. This is possible since the custom entities define both the state and behavior. Before the UI binds to a custom entity, the custom entity copies over the properties of the DTO. This way, the data is available when the UI binds to a custom entity. Let us see this approach in listing 2:


Listing 2


// Model Layer
using System;

public class EmployeeDTO
{
// properties
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Designation { get; set; }
public int Age { get; set; }

// constructor
public EmployeeDTO () {}

// constructor
public EmployeeDTO (int employeeId, string name, string address, string designation, int age)
{
this.EmployeeID = employeeId;
this.Name = name;
this.Address = address;
this.Designation = designation;
this.Age = age;
}
}

// Business Logic Layer
using System;

public class Employee
{
// properties
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Designation { get; set; }
public int Age { get; set; }

// constructor
public Employee() {}

// constructor
public Employee (int employeeId, string name, string address, string designation, int age)
{
this.EmployeeID = employeeId;
this.Name = name;
this.Address = address;
this.Designation = designation;
this.Age = age;
}

// ------------------- CRUD Methods -------------------------------
public IList GetAllEmployees ()
{
return ConvertListOfEmployees (EmployeeDAL.GetAllEmployees ()); // convert to list of BO before sending to UI
}

public EmployeeDTO GetEmployeeById (int employeeId)
{
return MapToBO (EmployeeDAL.GetEmployeeById (employeeId)); // convert to BO before sending to UI
}

public int Save (Employee employee)
{
return EmployeeDAL.Save (MapToDTO (employee)); // convert to DTO before sending to UI
}


// ------------------- Converters ---------------------------------
// Convert list of EmployeeDTO to list of Employee
private void ConvertListOfEmployee (IList employeeList)
{
IList EmployeeCollection;

foreach (EmployeeDTO employee in employeeList)
{
EmployeeCollection.Add (MapToBO (employee));
}

return EmployeeCollection;
}

// Convert an EmployeeDTO to Employee
private Employee MapToBO (EmployeeDTO employee)
{
return new Employee (employee.EmployeeID, Name, Age, Address, Designation);
}

// Convert an Employee to EmployeeDTO
private Employee MapToDTO (Employee employee)
{
return new EmployeeDTO (employee.EmployeeID, Name, Age, Address, Designation);
}
}


As you can see clearly, the above Employee Entity follows the principle of encapsulation. Both the state and behavior are encapsulated within the entity. However, in addition to the CRUD methods, the entity has a set of converters which are used to convert a DTO to a CE and vice versa. In my view, this is the only shortcoming of using this approach which may incur some overhead. But this overhead is minimal and can be ignored easily.

         CE                   DTO
UI <----------> BLL <-----------> DAL
Fig 2


Why not use Custom Entities directly

Curios readers must be thinking “Why not just use custom entities throughout the layers” i.e. In addition to the UI, custom entities can be referenced by DAL as well. This way we don’t need to have an extra layer of data transfer objects. The answer to this is that referencing custom throughout will create a circular reference between the BLL and DAL. A reference to the DAL from the BLL is unidirectional. But if DAL also references the BLL, it results in a bidirectional reference which leads to a circular reference.


Summary

In this part, we saw how to use custom entities in conjunction with data transfer objects. We looked at two different techniques. The first technique uses DTOs for transfer of data through all the layers. This technique works well but does not follow the principle of encapsulation. Also, this leads to the confusion as what is the best place to define the association. Should we define it at the BLL layer or the Model layer?

The second technique uses DTOs only between the BLL and DAL. The UI communicates with the BLL through the custom entities. This approach removes both the problems the first approach, however; it incurs a slight overhead of converting custom entities to DTOs and vice versa.

With this, we come to the end of this series. But this is just not it. I plan to write more on custom entities as this has become the standard coding practice. Please do provide your feedback through your comments. Stay tuned for more...

Monday, August 10, 2009

Using Custom Entities in ASP.NET Applications – Part 2



This is the second part of my short series on using Custom Entities in asp.net applications. In this part we will see how association between custom entities is defined. We will also explore the different types of association between which can exist between custom entities.


Association between Entities

In the database world, relationship is a mandatory feature. Different tables are linked to each other through relationships. Relationships are defined by the help of primary keys. These primary keys are placed as reference (foreign keys) in other tables. In OO programming, this relationship between entities (or classes) is known as association. Each custom entity is uniquely identified by an entity identity or identifier. This entity identity maps to the primary key in the database.

In custom entities, an association is defined by placing the identity of one entity in the other. For example lets assume two entities Book and Author. Since a book always has an author (not to mention how many) we can define this association by placing the author identity in the book entity as show in listing 1:


Listing 1


public class Book
{
private int bookID;
private string title;
// other properties

private int AuthorID; // association

// other constructs
}



Association between Entities

In the following sections, we will look at the different types of association, also known as cardinality between entities. For this purpose, I will use the following entities:

• Customer
• Orders
• Products
• Suppliers



One-to-Many Association

In this type of association, one instance of an entity type is associated with multiple instances of the second type. For example, one Customer can have many Orders. In this case, the Customer is the owner of this association. So the Customer entity specifies the mapping by having a child list object of type Order as shown in listing 3:

Listing 3


public class Customer
{
private int CustomerID;
// other properties

private IList OrderCollection; // 1:M association
}



Many-to-One Association

In this type of association, multiple instances of one entity type are associated with a single instance of another type. For example, many Orders (owner) belong to one Customer. So each Order specifies the mapping by including the identity of the related Customer as shown in listing 4:

Listing 4


public class Order
{
private int OrderID;
// other properties

private int CustomerID; // M:1 association
}



Many-to-Many Association

In a many to many association, multiple instances of one entity type are associated with multiple instances of the other type. For example, many Products have many Suppliers and vice versa. In this case, both entities are the owner and have a child list collection of the related entity as shown in listing 5:

Listing 5


public class Product
{
private int ProductID;
// other properties

private IList SupplierCollection; // M:M association
}

public class Supplier
{
private int SupplierID;
// other properties

private IList ProductCollection; // M:M association
}



One-to-One Association

One to One association is not very common and exists in special cases. For example, if a database table is very large and most of the fields are rarely used then the database designer tends to separate out these fields in a different table to improve performance. But both the tables are still linked through the same identity. In custom entities, such association is presented by a single entity which has all the fields.


Using an Identifier or a Full-Blown Object

One question commonly asked on different forums is that when defining an association, should we use the entity identity (a primitive data type) or a full blown object of the entity being referenced. In other words, listing 1 can be rewritten as following:

Listing 6


public class Book
{
private int bookID;
private string title;
// other properties

private Author author; // association – Full Blown Object

// other constructs
}


Watch closely, in the above listing, we are not using the simple AuthorID of type integer to define the mapping. Rather we have used a child object of type ‘Author’. This is one approach taken by developers. To me, the answer to the above question depends on different factors including the technology being used plus the user requirements. Let me explain both these scenarios in details.

First, ASP.NET comes with many built in controls which make data binding a breeze. These controls including the ObjectDataSource, GridView, ListView etc are capable of binding to custom entities as well. However, these controls can only bind to properties of primitive types (int, string, bit etc). These controls cannot bind to complex child object or collection. To me, this is a short coming in the framework and hopefully will be removed in a future version. Although there are workaround, but they do not offer a concrete solution. So if the custom entity contains a reference of simple type, it can easily bind to a data control.

Second, the user requirement also plays an important role. Suppose we are creating an application for a retail outlet. A Customer makes an Order for different purchases. This customer may already exist in the system. Now if we have modeled our Order class to have a full blown Custom child object, we can easily create both the Order and the Customer object. Why because we have full access to the Customer object through the Order object. This way when the Order is passed down to the DAL, the entire Customer object is passed along and saved to the database. On the other hand, if the Order only had a reference to Customer identity, we first had to create a new Customer and then assign his identity to the Order object. This would be more like a two step process.

In the end, to me it remains a user preference whether to use a reference of simple or custom type. Different factors play in and have to be considered before preference is locked down.



Light-Weight Model and Association

When it comes to architecture, different people have different opinions (and they are justified as well). When defining association between entities, it tends to get very complex and difficult to handle. Custom Entities may have a deep hierarchy of association. For example, a Product is composed of Components. Each Component has many Parts and each Part may be made up of Sub-Parts. With such hierarchy, many issues have to be considered. For example, if we make changes at any level or the hierarchy, the entire hierarchy has to be persisted. Similarly, if we are making changes at any level and the parent hierarchy leaves the transaction, all the properties have to be restored back to the original state. There are numerous scenarios with such deep hierarchy.

An alternative to deal with such associations is by defining a light-weight model. This means that there is no need to have a child object with the parent object. We can instead use method (or more specifically services) to fetch the child data. This is more like a Service-Oriented Architecture where we tend to rely on services. The concept is to simply fetch the data when required.

For example, using the above approach, we can rewrite listing 1 as following:

Listing 7


public class Book
{
private int bookID;
private string title;
// other properties

public Author GetBookAuthor ()
{
//return GetBookAuthor (this.bookID)
}

// other constructs
}


In the above listing, an Author object is returned using the method GetBookAuthor. This eliminates the need to reference the Author object within the Book class. I am sure you can see the advantages of using this approach. However, my opinion is not final.


Summary

In this post, we saw the how association is defined between entities. We also looked at the different types of associations also known as ‘cardinality’. We also looked at the different scenarios which lead to deciding whether to use a reference of primitive type or a full blown object. In the next post, we will see how to code around custom entities. Stay tuned for more…

Friday, August 7, 2009

Using Custom Entities in ASP.NET Applications – Part 1



Recently there has been a surge of architecture-related discussion in the .NET community. This stems from the fact that business applications are getting complex and intricate to build. Building N-Tier business applications is both a requirement and a challenging task. This cannot be achieved by just using a specific framework such as the .NET Framework. The .NET Framework does provide a rich library for building enterprise business applications but this is half the story. Sound Object-Oriented principles supported by architectural patterns apply across all development platforms without targeting a specific technolgy. This combination of technology, OO principle and architecture results in applications which are scalable, fault tolerant and user interactive.

In this short series, I will talk about using Business Entities in ASP.NET applications. The reason behind this series to present my two cents on most of the question asked on the forums regarding developing N-Tier applications using Custom Entities. This discussion is not intended to explain OO programming. The focus is to discuss architecture issues when using Custom Entities. I will start with simple concepts and then extend it from there.



What’s wrong with DataSet

Honestly speaking, DataSets are not evil at all and I prefer to use them whenever I can. It’s easy to program around a DataSet and IMHO, works great for small to mid sized applications. If you really fine tune the data layer accessing the database, a DataSet gives optimal performance. In addition to this, many of the data controls available in asp.net including ObjectDataSource, GridView, Datalist etc work really well with DataSets. However, a DataSet has its limitations and is not suited for every situation especially when used for Enterprise Applications. The most commonly faced problems include:

• They are not strongly-typed
• They lack validation and business rules.
• They do not support OO principles such as Encapsulation, Inheritance etc
• DataSet have a performance issue when used for large amount of data (see this)
• DataSets are not interoperable with applications written in other languages such as Java, PHP etc
• The use of DataSet dictates the Data-First design whereas OO principles focuses on Domain-First design
• Maintenance becomes difficult when an application starts growing with time (which every application does)

The alternative is to use custom entities discussed in the following section.



Using Custom Entities

Seasoned programmers tend to use classes for developing business applications. Classes allow the developers to take advantage of a rich OO programming model. This model comes with a set of well defined OO principles including Data Abstraction, Information Hiding, Encapsulation, Inheritance etc.

In its essence, a custom entity is just a regular class. But what makes it different is that it is a domain object. In business applications, domain objects identify the key entities within the system. Each domain object can be represented by a Custom Entity.

In addition to supporting OO principles, a custom entity defines business rules and custom validation. This subtle addition is the real difference between a regular class and a custom entity. For example, let’s look at the following Book custom entity:




public class Book
{
// properties
public int BookId { get; set; }
public string ISBN { get; set; }
public string Title { get; set; }
public string Author { get; set; }

// constructors
public Book () {}

public Book (string isbn, string title, string author)
{
// set values
}

// simple method
public int BuyBook (string ISBN)
{
// process
}

// validation rule
public book Validate (Book book)
{
if (book.ISBN == null)
return false;
// other rules
}

// business rule
public int isPremiumMember (int customerId)
{
// if customer is a premium member
// eligible for gift voucher
// return voucherNumber
}
}


The above entity defines the normal properties, constructors and a method (BuyBook). In addition to these constructs, the class also defines a validation method (Validate) and a business rule (isPremiumMember). The Validate method validates the state of the object while isPremiumMember method determines if the customer is eligible for a gift voucher given he is a premium member. This is just a trivial example. True custom entities can have a complex set of business rules.

Different terms including Business Object, Business Entity and Custom Business Entity are used interchangeably to represent a Custom entity. Though the purists may differentiate between them but IMHO, they all are the same. It’s just a preference of term used by different users.



Data Transfer Objects

Data Transfer Object (DTO) is a design pattern used to transfer data between software application subsystems. It is basically a data container. The main difference between a DTO and a Custom Entity is that a DTO does not have any behavior or responsibility and only consists of properties. A DTO is also known as a dumb object due to the lack of any behavior. Using a DTO has several advantages including:

• All data is summed up in one DTO and passed down to a layer
• Since an entire object is passed down the wire, adding or removing properties to the object does not effect the calls
• DTOs are light weight objects which give better as compared to DataSets



Keeping above in mind, the book BO in the above section can have the following corresponding Book DTO:



public class BookDTO
{
public int BookId { get; set; }
public string ISBN { get; set; }
public string Title { get; set; }
public string Author { get; set; }

public Book () {}

public Book (string isbn, string title, string author)
{
// set values
}
}


Using Custom Entities and DTOs

A typical 3-tier (logical) application has three layers namely User Interface Layer (UI), Business Logic Layer (BLL) and the Data Access Layer (DAL). The UI layer provides an interface to the user to interact with the system. The BLL (application layer, middle layer) is where all the business logic resides and the DAL deals with operations of the data source. The UI never interacts with the DAL directly. When a user makes a request from the UI, the request is directed to the BLL. The BLL then forwards the request to the DAL. The typical flow of a user request is as following:

UI <-> BLL <-> DAL

The question is how the data transfers between the layers? This is where the DTOs come into play. When the user request reaches the DAL, the DAL fetches the data from the data source and bundles it into a DTO. The DTO is then returned to the BLL followed by the UI. Similarly when a user creates or updates a record, the entire DTO is transferred back to the BLL and then to the DAL.
The update and delete process can be handled by just using the primary key value.



Is a DTO a Custom Entity

This is an interesting question. I have seen many applications where both the terms are used interchangeably. There is no harm in doing so but I tend to disagree. A DTO is really a design pattern used to transfer data between subsystems. Although it a class but keep in mind that a DTO does not define any behavior, business rules, validation or relationship. In the following posts, I will show you how a DTO is used both as a custom entity and individually.


Summary

In this post, I just gave you an overview of what Custom entities are and tried to understand the basics of using Custom Entities when developing business applications. In the following post, we will dive deeper and explore more about custom entities.