Monday, April 25, 2016
Data access layer - Load data into objects from store procedure - efficient/optimized way - Using lambda exprssion
Data access layer - Load data into objects from store procedure
private IDataReader dataReader;
/// <summary>
/// Execute Procedure Using Expression Tree
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="procedureName"></param>
/// <param name="parameters"></param>
/// <returns>IEnumerable<T> </returns>
public IEnumerable<T> LoadDataFromProcedure<T>(string procedureName, IDictionary<string, IConvertible> parameters = null) where T : class, new()
{
var list = new List<T>();
using (var reader = this.ExecuteReader(procedureName, parameters))
{
if (reader.HasRows)
{
this.dataReader = reader;
Func<IDataReader, T> CreateItemFromRow = GetMapFromDBReaderCompile<T>();
while (reader.Read())
{
list.Add(CreateItemFromRow(reader));
}
}
reader.Close();
}
return list;
}
/// <summary>
/// GetMapFunc
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private Func<IDataReader, T> GetMapFromDBReaderCompile<T>()
{
int _fieldCount = dataReader.FieldCount;
List<Expression> _expression = new List<Expression>();
ParameterExpression readerExpression = Expression.Parameter(typeof(IDataRecord));
ParameterExpression objectExpression = Expression.Variable(typeof(T));
_expression.Add(Expression.Assign(objectExpression, Expression.New(objectExpression.Type)));
PropertyInfo indexerInfo = typeof(IDataRecord).GetProperty("Item", new[] { typeof(int) });
var columnNames = Enumerable.Range(0, _fieldCount).Select(i => new { i, name = dataReader.GetName(i) }).AsParallel();
foreach (var column in columnNames)
{
PropertyInfo property = objectExpression.Type.GetProperty(column.name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (property != null)
{
ConstantExpression columnNameExpression = Expression.Constant(column.i);
IndexExpression propertyExpression = Expression.MakeIndex(readerExpression, indexerInfo, new[] { columnNameExpression });
BinaryExpression assignExpression = Expression.Assign(Expression.Property(objectExpression, property), Expression.Condition(Expression.Equal(propertyExpression, Expression.Constant(DBNull.Value)), Expression.Default(property.PropertyType), Expression.Convert(propertyExpression, property.PropertyType)));
_expression.Add(assignExpression);
}
}
_expression.Add(objectExpression);
return Expression.Lambda<Func<IDataReader, T>>(Expression.Block(new[] { objectExpression }, _expression), readerExpression).Compile();
}
private IDataReader dataReader;
/// <summary>
/// Execute Procedure Using Expression Tree
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="procedureName"></param>
/// <param name="parameters"></param>
/// <returns>IEnumerable<T> </returns>
public IEnumerable<T> LoadDataFromProcedure<T>(string procedureName, IDictionary<string, IConvertible> parameters = null) where T : class, new()
{
var list = new List<T>();
using (var reader = this.ExecuteReader(procedureName, parameters))
{
if (reader.HasRows)
{
this.dataReader = reader;
Func<IDataReader, T> CreateItemFromRow = GetMapFromDBReaderCompile<T>();
while (reader.Read())
{
list.Add(CreateItemFromRow(reader));
}
}
reader.Close();
}
return list;
}
/// <summary>
/// GetMapFunc
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private Func<IDataReader, T> GetMapFromDBReaderCompile<T>()
{
int _fieldCount = dataReader.FieldCount;
List<Expression> _expression = new List<Expression>();
ParameterExpression readerExpression = Expression.Parameter(typeof(IDataRecord));
ParameterExpression objectExpression = Expression.Variable(typeof(T));
_expression.Add(Expression.Assign(objectExpression, Expression.New(objectExpression.Type)));
PropertyInfo indexerInfo = typeof(IDataRecord).GetProperty("Item", new[] { typeof(int) });
var columnNames = Enumerable.Range(0, _fieldCount).Select(i => new { i, name = dataReader.GetName(i) }).AsParallel();
foreach (var column in columnNames)
{
PropertyInfo property = objectExpression.Type.GetProperty(column.name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
if (property != null)
{
ConstantExpression columnNameExpression = Expression.Constant(column.i);
IndexExpression propertyExpression = Expression.MakeIndex(readerExpression, indexerInfo, new[] { columnNameExpression });
BinaryExpression assignExpression = Expression.Assign(Expression.Property(objectExpression, property), Expression.Condition(Expression.Equal(propertyExpression, Expression.Constant(DBNull.Value)), Expression.Default(property.PropertyType), Expression.Convert(propertyExpression, property.PropertyType)));
_expression.Add(assignExpression);
}
}
_expression.Add(objectExpression);
return Expression.Lambda<Func<IDataReader, T>>(Expression.Block(new[] { objectExpression }, _expression), readerExpression).Compile();
}
Subscribe to:
Posts (Atom)
Encrypt/Decrypt the App.Config
Program.cs using System; using System.Diagnostics; using System.IO; namespace EncryptAppConfig { internal class Program { pr...
-
C# Style Guide Remember that at the end of the day these are only recommendations . Table of Contents Tooling General Layout Spa...
-
RazorGenerator Generator Types MvcHelper : Creates a static type that is best suited for writing Mvc specific helper methods. MvcV...
-
private XDocument RemoveNamespace(XDocument xdoc) { foreach (XElement e in xdoc.Root.Descendants()) { ...