I made some improvements on my dal. But I still have an issue to load the cache with the propertiesInfo via reflection.
I do 2 Activator.CreateInstace(T).
Each CreateInstance is heavy and sould I try to make all work with just one or it´s not worth it?
I cache the info into (cachedPropsInfo). Before I was doing a reflection call each time I would need the info.
As far as I know, reflection is not free, but doing the timming, I don´t see too much difference using the cached info...
Am I doing the cache in the right way or this tunning that I did and nothing are the same things?
cheers
Here is part of the code.
namespace DAL
{
public abstract class BaseRepository<T> where T : BaseEntity
{
private static Dictionary<PropertyInfo, DbPropsInfo> cachedPropsInfo;
private IEnumerable<T> fetchRecords(DbCommand dbCommand, bool isSingleRecord)
{
if (dbCommand.IsNull())
throw new ArgumentNullException("DbCommand is null");
#if DEBUG
debugParameters(dbCommand, "FetchRecords");
#endif
CommandBehavior behavior = CommandBehavior.CloseConnection;
if (isSingleRecord)
behavior ^= CommandBehavior.SingleRow;
IList<T> list = new List<T>();
using (DbConnection dbconn = db.CreateConnection())
{
dbCommand.Connection = dbconn;
try
{
dbconn.Open();
using (var rd = dbCommand.ExecuteReader(behavior))
{
try
{
if (rd?.HasRows == true)
{
DateTime dt1 = DateTime.Now;
**cachedPropsInfo = Activator.CreateInstance<T>().GetDbInfoProps();**
while (!rd.IsNull() && rd.Read())
{
list.Add(MapTo<T>(rd));
}
DateTime dt2 = DateTime.Now;
System.Diagnostics.Debug.WriteLine($"Took {(dt2-dt1).TotalMilliseconds}");
}
}
catch(Exception ex)
{
string error = mountErrorMsg("Fetch Records Reader", dbCommand, ex);
throw;
}
finally
{
if (rd?.IsClosed == false)
rd.Close();
}
}
}
catch (Exception ex)
{
string error = mountErrorMsg("Fetch Records Command", dbCommand, ex);
throw;
}
finally
{
dbCommand?.Dispose();
dbconn?.Dispose();
if (dbconn?.State == ConnectionState.Open)
dbconn.Close();
}
}
return list.AllOrNull();
}
protected T MapTo<T>(DbDataReader record)
{
if (record.IsNull())
throw new ArgumentNullException("Datareader record is null");
**T obj = Activator.CreateInstance<T>();**
string colName = null;
string propName = null;
object objValue = null;
Type toType = null;
try
{
foreach (var prop in cachedPropsInfo)
{
propName = prop.Key.Name;
colName = prop.Value.DbColumnName;
toType = prop.Value.ToType;
objValue = record[colName];
prop.Key.SetValue(obj, (DBNull.Value == objValue) ? null : Convert.ChangeType(objValue, toType));
}
}
catch (Exception ex)
{
string msg = $@"MapTo SetValue, Model: {this.GetType().Name},
Property: '{propName}', ColumnDB: '{colName}',
PropType: '{toType.ToString()}',
Value: '{objValue.ToString()}', Exception: {ex.Message}";
throw;
}
return obj;
}
public Dictionary<PropertyInfo, DbPropsInfo> GetDbInfoProps()
{
var tca = typeof(DbColumnAttribute);
var y = new Dictionary<PropertyInfo, DbPropsInfo>();
string colName = "";
Type toType = null;
foreach (var prop in this.GetType().GetProperties().Where(x => x.IsDefined(tca, true)))
{
colName = ((DbColumnAttribute)prop.GetCustomAttributes(true)
.SingleOrDefault(x => x.GetType() == tca)).ColumnName;
toType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
y.Add(prop, new DbPropsInfo { DbColumnName = colName, ToType = toType });
}
return y;
}
Aucun commentaire:
Enregistrer un commentaire