Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Communication via Collection: Business Object, Business Entity & Data Access Layer

0.00/5 (No votes)
21 Apr 2014 1  
Collection based design

Introduction

Most of the Software Architects want to make communication between User Interfaces, Business objects and Data Access layer using object collections. In this tip, I want to discuss how we can design our application.

Background

Now a days, I am working on a very big product which has hundreds of business entity and business object. Business objects communicate via database using entity object and XML.

Why they want to use collection based communication is not the scope of this article.

In the .NET application, we receive the tabular data from the database in the object of DataTable or DataSet. Before returning it to the Business object, we convert the object of DataTable to the collection.

First of all, we create an Entity class.

Public class Entity
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
    public string Property3 { get; set; }
    public string Property4 { get; set; }
} 

The next step is to map the Entity properties with the DataTable columns.

To map business entity properties with data table columns, we define a class which can be used like an attribute. Hence this class should be inherited with the System.Attribute class.

 public class BusinessEntityAttribute : System.Attribute
{
    /// <summary>
    /// Database field name.
    /// </summary>
    public string DBFieldName { get; set; }
    /// <summary>
    /// Field null value
    /// </summary>
    public object NullValue { get; set; }        
    public string Format { get; set; }
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="dbFieldName"></param>
    /// <param name="nullValue"></param>
    public BusinessEntityAttribute(string dbFieldName, string nullValue, 
      string format="") : base()
    {
        this.DBFieldName = dbFieldName;
        this.NullValue = nullValue;
        this.Format = format;
    }
}

Now we are ready to map entity class properties and data table columns:

public class Entity
{
    [BusinessEntityAttribute("COLUMN1", "","")]
    public string Property1 { get; set; }
    [BusinessEntityAttribute("COLUMN2", "","")]
    public string Property2 { get; set; }
    [BusinessEntityAttribute("COLUMN3", "","")]
    public string Property3 { get; set; }
    [BusinessEntityAttribute("COLUMN4", "","")]
    public string Property4 { get; set; }
}

Here COLUMN1 is the name of a column which we get from the database.

As you know, in .NET we store tabular data in the DataTable object. So we have to create a method which can take the object of DataTable and can return the collection of Entity objects. Since we have hundreds of entity classes, we must have to write a generic method which can be used for each of the entity classes.

public static List<T> ConvertDatatableToList<T>(DataTable dataTable) where T : new()
{
List<T> list = null;
if (dataTable != null)
{
    list = new List<T>();
    //iterate rows of given table
    foreach (DataRow dataRow in dataTable.Rows)
    {
        T businessEntityObject = new T();
        //get the list of property present in the given data type
        PropertyInfo[] pi = businessEntityObject.GetType().GetProperties();
        //iterate all the property and set its value
        foreach (PropertyInfo prop in pi)
        {
            BusinessEntityAttribute businessObjectAttributes = 
            (BusinessEntityAttribute)Attribute.GetCustomAttribute(prop, typeof(BusinessEntityAttribute));
            //only load bound properties that are not null
            if (businessObjectAttributes != null &&
            businessObjectAttributes.DBFieldName != string.Empty &&
            dataTable.Columns.Contains(businessObjectAttributes.DBFieldName) &&
            dataRow[businessObjectAttributes.DBFieldName] != DBNull.Value)
            {
                //set value from the datatable/rows into the collection
                if (prop.PropertyType == typeof(DateTime) || 
                prop.PropertyType == typeof(DateTime?))
                {
                    prop.SetValue(businessEntityObject, ((DateTime)(dataRow[businessObjectAttributes.DBFieldName])), null);
                }
                else if (prop.PropertyType == typeof(Double) && 
                !string.IsNullOrWhiteSpace(businessObjectAttributes.Format)
                {
                prop.SetValue(businessEntityObject, dataRow[businessObjectAttributes.DBFieldName] == 
                DBNull.Value ? 0 : Math.Round(Convert.ToDouble(dataRow[businessObjectAttributes.DBFieldName]), 
                int.Parse(businessObjectAttributes.Format)), null);
                }
                else
                    prop.SetValue(businessEntityObject, dataRow[businessObjectAttributes.DBFieldName] == 
                    DBNull.Value ? businessObjectAttributes.NullValue : Convert.ChangeType
                    (dataRow[businessObjectAttributes.DBFieldName], prop.PropertyType), null);
                }
            }
            list.Add(businessEntityObject);
        };
    }
    return list; 
} 

So, we can use the above methods to convert DataTable object to Entity collection:

List<Entity> lstEntity = ConvertDatatableToList<Entity>(dt); 

Till now, we have completed one part (receive data from the database). Next part is we have to send back the entity object to the database ( stored procedure).

We have to write a generic code so that we can use this code for each of the entity classes/objects. Here, we can use XML to send the entity object to the stored procedure. To send the entity object to the stored procedure, we have to serialize the entity objects to prepare the XML data.

There are two ways to do this:

  1. We can use Xml attribute to define the XML element name for serialization:
       [Serializable]
    [XmlRoot("Entity")]
    public class Entity
    {
        [XmlElement("COLUMN1")]
        [BusinessEntityAttribute("COLUMN1", "","10")]
        public string Property1 { get; set; }    
    
    ...
    }
  2. In the first approach, we use XmlElement attribute to define the element while serializing entity object. In this case, we have to add two attributes with the same column name “COLUMN1”. It is a little bit overhead.

    public class BusinessEntityAttribute : XmlElementAttribute
    {
        …
    }

The next and last step is to serialize the entity class/object:

XmlSerializer serializer = new XmlSerializer(typeof(Entity));
XmlSerializerNamespaces xmlNamespace = new XmlSerializerNamespaces();
xmlNamespace.Add(string.Empty, string.Empty);
StringBuilder sb = new StringBuilder();
using (XmlWriter xw = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true }))
{
    serializer.Serialize(xw, entity, xmlNamespace);
}  

Thanks and happy programming.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here