/// <summary> /// Query IEnumerable<T> by sql /// </summary> /// <typeparam name="T"></typeparam> /// <param name="context"></param> /// <param name="sql"></param> /// <param name="args"></param> /// <returns></returns> public static IEnumerable <T> Query <T>(this IRepositoryContext context, string sql, params object[] args) where T : new() { using (var dr = context.ExecuteDataReader(sql)) { if (dr.HasRows) { var propCache = new Dictionary <string, PropertyInfo>(); var drFields = new List <string>(); for (var i = 0; i < dr.FieldCount; i++) { drFields.Add(dr.GetName(i)); } while (dr.Read()) { var insT = new T(); if (propCache.Count == drFields.Count) { var propList = insT.GetType().GetProperties(); foreach (var field in drFields) { var prop = propCache[field]; var value = dr[field]; if (value != DBNull.Value) { prop.SetValue(insT, value, null); } } } else { var propList = insT.GetType().GetProperties(); foreach (var prop in propList) { var field = prop.Name; if (!drFields.Contains(field)) { continue; } if (!prop.CanWrite) { continue; } var value = dr[field]; if (value != DBNull.Value) { prop.SetValue(insT, value, null); } if (!propCache.ContainsKey(field)) { propCache.Add(field, prop); } } // Re-balance PropCache & drFields if (propCache.Count != drFields.Count) { var interset = drFields.Intersect(propCache.Select(x => x.Key)).ToList(); drFields = interset; var subSet = propCache.Select(x => x.Key).Except(interset); foreach (var item in subSet) { propCache.Remove(item); } } } yield return(insT); } } } }