mardi 25 octobre 2016

C# Reflection tunning DAL

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