Following code helps me to automatically map the query result with Entity properties. For example, result of the following query “ReportTypeCode“ is mapped with Report object’s ReportTypeCode property.
SELECT R.report_type_code AS ReportTypeCode FROM Report_Type R
QUESTIONS
- Is there any datatype or scenario that it will not be able to handle?
- Is there any improvement suggestions?
CODE
public static class EntityDataMappingHelper
{
/// <summary>
/// Method for filling entity from data
/// </summary>
public static void FillEntityFromRecord(Object entity, Dictionary<string, object> record)
{
if (entity != null && record != null)
{
PropertyInfo[] propertyInfoArray = entity.GetType().GetProperties();
foreach (PropertyInfo prop in propertyInfoArray)
{
if (record.ContainsKey(prop.Name))
{
if (String.Equals(prop.PropertyType.FullName, "System.String"))
{
prop.SetValue(entity, DBNull.Value.Equals(record[prop.Name]) ? null : Convert.ToString(record[prop.Name], CultureInfo.InvariantCulture), null);
}
else if (String.Equals(prop.PropertyType.FullName, "System.Decimal"))
{
prop.SetValue(entity, DBNull.Value.Equals(record[prop.Name]) ? 0 :
Convert.ToDecimal(record[prop.Name], CultureInfo.InvariantCulture), null);
}
else
{
prop.SetValue(entity, DBNull.Value.Equals(record[prop.Name]) ? null : record[prop.Name], null);
}
}
}
}
}
/// <summary>
/// Method for selecting records from Data Reader
/// </summary>
public static ArrayList SelectRecords(Collection<Object> entityList, IDataReader reader)
{
ArrayList resultList = new ArrayList();
if (entityList != null && reader != null)
{
List<string> propertiesOfAllEntities = new List<string>();
foreach (Object entity in entityList)
{
PropertyInfo[] propertyInfo = entity.GetType().GetProperties();
foreach (PropertyInfo prop in propertyInfo)
{
propertiesOfAllEntities.Add(prop.Name);
}
}
while (reader.Read())
{
Dictionary<string, object> record = MapPropertiesToReaderValues(propertiesOfAllEntities, reader);
resultList.Add(record);
}
}
return resultList;
}
/// <summary>
/// Helper method for mapping properties with reader values
/// </summary>
private static Dictionary<string, object> MapPropertiesToReaderValues(List<string> propertiesOfAllEntities, IDataReader reader)
{
Dictionary<string, object> propertyResultList = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < reader.FieldCount; i++)
{
string readerFieldName = reader.GetName(i);
//Whether propertiesOfAllEntities.Contains the property
if (propertiesOfAllEntities.FindIndex(x => x.Equals(readerFieldName, StringComparison.OrdinalIgnoreCase)) != -1)
{
propertyResultList.Add(readerFieldName, reader[i]);
}
}
return propertyResultList;
}
}
Client to Test
static void Main(string[] args)
{
Collection<Report> reports = new Collection<Report>();
string connectionString = "Data Source=myserver;Initial Catalog=mydatabase;Integrated Security=SSPI";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string commandText = @"SELECT R.report_type_code AS ReportTypeCode
FROM Report_Type R";
using (SqlCommand command = new SqlCommand(commandText, connection))
{
command.CommandType = System.Data.CommandType.Text;
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
Collection<Object> entityList = new Collection<Object>();
entityList.Add(new Report());
ArrayList records = EntityDataMappingHelper.SelectRecords(entityList, reader);
for (int i = 0; i < records.Count; i++)
{
Report report = new Report();
Dictionary<string, object> currentRecord = (Dictionary<string, object>)records[i];
EntityDataMappingHelper.FillEntityFromRecord(report, currentRecord);
reports.Add(report);
}
}
}
}
}
Console.ReadLine();
}
DTO/Entity
public class Report
{
public Int16? ReportTypeCode { get; set; }
public string ReportName { get; set; }
}