using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public partial class DbBindAccessory { public QueryBuilder QueryBuilder { get; set; } protected List GetEntityList(SqlSugarProvider context, IDataReader dataReader) { Type type = typeof(T); var entityInfo = context.EntityMaintenance.GetEntityInfo(type); var isOwnsOne = entityInfo.Columns.Any(it => it.ForOwnsOnePropertyInfo != null); string types = null; var fieldNames = GetDataReaderNames(dataReader,ref types); string cacheKey = GetCacheKey(type,fieldNames) + types; var dataAfterFunc = context.CurrentConnectionConfig?.AopEvents?.DataExecuted; IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => { var cacheResult = new IDataReaderEntityBuilder(context, dataReader,fieldNames).CreateBuilder(type); return cacheResult; }); List result = new List(); try { if (dataReader == null) return result; while (dataReader.Read()) { //try //{ var addItem = entytyList.Build(dataReader); if (this.QueryBuilder?.QueryableFormats?.Any() == true) { FormatT(addItem); } result.Add(addItem); //} //catch (Exception ex) //{ // Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); //} SetAppendColumns(dataReader); SetOwnsOne(addItem,isOwnsOne,entityInfo,dataReader); } ExecuteDataAfterFun(context, dataAfterFunc, result); } catch(Exception ex) { if (ex.Message == "Common Language Runtime detected an invalid program.") { Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); } else { throw; } } return result; } protected async Task> GetEntityListAsync(SqlSugarProvider context, IDataReader dataReader) { Type type = typeof(T); var entityInfo = context.EntityMaintenance.GetEntityInfo(type); var isOwnsOne = entityInfo.Columns.Any(it => it.ForOwnsOnePropertyInfo != null); string types = null; var fieldNames = GetDataReaderNames(dataReader,ref types); string cacheKey = GetCacheKey(type, fieldNames)+types; var dataAfterFunc = context.CurrentConnectionConfig?.AopEvents?.DataExecuted; IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => { var cacheResult = new IDataReaderEntityBuilder(context, dataReader, fieldNames).CreateBuilder(type); return cacheResult; }); List result = new List(); try { if (dataReader == null) return result; while (await GetReadAsync(dataReader,context)) { //try //{ var addItem = entytyList.Build(dataReader); if (this.QueryBuilder?.QueryableFormats?.Any() == true) { FormatT(addItem); } result.Add(addItem); //} //catch (Exception ex) //{ // Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); //} SetAppendColumns(dataReader); SetOwnsOne(addItem, isOwnsOne, entityInfo, dataReader); } ExecuteDataAfterFun(context, dataAfterFunc, result); } catch (Exception ex) { if (ex.Message == "Common Language Runtime detected an invalid program.") { Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); } else { throw; } } return result; } private Task GetReadAsync(IDataReader dataReader, SqlSugarProvider context) { if (this.QueryBuilder?.Builder?.SupportReadToken==true&&context.Ado.CancellationToken!=null) { return this.QueryBuilder.Builder.GetReaderByToken(dataReader, context.Ado.CancellationToken.Value); } else { return ((DbDataReader)dataReader).ReadAsync(); } } private void SetOwnsOne(object addItem, bool isOwnsOne, EntityInfo entityInfo, IDataReader dataReader) { if (isOwnsOne) { var ownsOneColumnsKv = entityInfo.Columns.Where(it => it.ForOwnsOnePropertyInfo != null) .GroupBy(it=>it.ForOwnsOnePropertyInfo).ToList(); foreach (var kv in ownsOneColumnsKv) { var parentObj=kv.Key.GetValue(addItem); if (parentObj == null) { parentObj = kv.Key.PropertyType.Assembly.CreateInstance(kv.Key.PropertyType.FullName); kv.Key.SetValue(addItem, parentObj); } foreach (var item in kv.ToList()) { if (this.QueryBuilder?.SelectValue?.Equals("1")==true) { continue; } var itemIndex=dataReader.GetOrdinal(item.DbColumnName); if (item.SqlParameterDbType is Type&&item.UnderType.IsEnum && dataReader.GetValue(itemIndex) is string value) { item.PropertyInfo.SetValue(parentObj,UtilMethods.ChangeType2(value, item.PropertyInfo.PropertyType)); } else if (item.IsJson) { item.PropertyInfo.SetValue(parentObj, Newtonsoft.Json.JsonConvert.DeserializeObject(dataReader.GetValue(itemIndex)?.ToString(), item.PropertyInfo.PropertyType)); } else { var setValue = dataReader.GetValue(itemIndex); if (setValue == DBNull.Value) { setValue = null; } if (item.UnderType == UtilConstants.GuidType&& setValue is string) { if (setValue != null) { setValue = Guid.Parse(setValue+""); } } else if (item.UnderType?.IsEnum==true&& setValue!=null) { setValue = UtilMethods.ChangeType2(setValue, item.UnderType); } item.PropertyInfo.SetValue(parentObj, setValue); } } } } } private void FormatT(T addItem) { var formats = this.QueryBuilder.QueryableFormats; var columns = this.QueryBuilder.Context.EntityMaintenance.GetEntityInfoWithAttr(typeof(T)) .Columns.Where(it => formats.Any(y => y.PropertyName == it.PropertyName)).ToList(); if (columns.Any()) { foreach (var item in formats) { var columnInfo = columns.FirstOrDefault(it => it.PropertyName == item.PropertyName); var value = columnInfo.PropertyInfo.GetValue(addItem); value = UtilMethods.GetFormatValue(value, item); columnInfo.PropertyInfo.SetValue(addItem, value); } } } private static void ExecuteDataAfterFun(SqlSugarProvider context, Action dataAfterFunc, List result) { if (dataAfterFunc != null) { ((AdoProvider)context.Ado).AfterTime = DateTime.Now; var entity = context.EntityMaintenance.GetEntityInfo(); foreach (var item in result) { dataAfterFunc(item, new DataAfterModel() { EntityColumnInfos = entity.Columns, Entity = entity, EntityValue = item }); } } } private string GetCacheKey(Type type,List keys) { StringBuilder sb = new StringBuilder("DataReaderToList."); sb.Append(type.FullName); sb.Append("."); foreach (var item in keys) { sb.Append(item); } return sb.ToString(); } private void SetAppendColumns(IDataReader dataReader) { if (QueryBuilder != null && QueryBuilder.AppendColumns != null && QueryBuilder.AppendColumns.Any()) { if (QueryBuilder.AppendValues == null) QueryBuilder.AppendValues = new List>(); List addItems = new List(); foreach (var item in QueryBuilder.AppendColumns) { var vi = dataReader.GetOrdinal(item.AsName); var value = dataReader.GetValue(vi); addItems.Add(new QueryableAppendColumn() { Name = item.Name, AsName = item.AsName, Value = value }); } QueryBuilder.AppendValues.Add(addItems); } if (QueryBuilder?.AppendNavInfo != null) { var navResult = new AppendNavResult(); foreach (var item in QueryBuilder?.AppendNavInfo.AppendProperties) { var vi = dataReader.GetOrdinal("SugarNav_" + item.Key); var value = dataReader.GetValue(vi); navResult.result.Add("SugarNav_"+item.Key,value); } QueryBuilder?.AppendNavInfo.Result.Add(navResult); } } private List GetDataReaderNames(IDataReader dataReader,ref string types) { List keys = new List(); StringBuilder sbTypes = new StringBuilder(); var count = dataReader.FieldCount; for (int i = 0; i < count; i++) { keys.Add(dataReader.GetName(i)); var type = dataReader.GetFieldType(i); if (type != null) { sbTypes.Append(type.Name.Substring(0, 2)); } } types = sbTypes.ToString(); return keys; } protected List GetKeyValueList(Type type, IDataReader dataReader) { List result = new List(); while (dataReader.Read()) { GetKeyValueList(type, dataReader, result); } return result; } protected async Task> GetKeyValueListAsync(Type type, IDataReader dataReader) { List result = new List(); while (await ((DbDataReader)dataReader).ReadAsync()) { GetKeyValueList(type, dataReader, result); } return result; } private static void GetKeyValueList(Type type, IDataReader dataReader, List result) { if (UtilConstants.DicOO == type) { var kv = new KeyValuePair(dataReader.GetValue(0), dataReader.GetValue(1)); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else if (UtilConstants.DicIS == type) { var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToString()); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else if (UtilConstants.Dicii == type) { var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToInt()); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else if (UtilConstants.DicSi == type) { var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToInt()); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else if (UtilConstants.DicSo == type) { var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1)); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else if (UtilConstants.DicSS == type) { var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToString()); result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); } else { Check.Exception(true, ErrorMessage.NotSupportedDictionary); } } protected async Task> GetArrayListAsync(Type type, IDataReader dataReader) { List result = new List(); int count = dataReader.FieldCount; var childType = type.GetElementType(); while (await((DbDataReader)dataReader).ReadAsync()) { GetArrayList(type, dataReader, result, count, childType); } return result; } protected List GetArrayList(Type type, IDataReader dataReader) { List result = new List(); int count = dataReader.FieldCount; var childType = type.GetElementType(); while (dataReader.Read()) { GetArrayList(type, dataReader, result, count, childType); } return result; } private static void GetArrayList(Type type, IDataReader dataReader, List result, int count, Type childType) { object[] array = new object[count]; for (int i = 0; i < count; i++) { array[i] = Convert.ChangeType(dataReader.GetValue(i), childType); } if (childType == UtilConstants.StringType) result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToString()).ToArray(), type)); else if (childType == UtilConstants.ObjType) result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? null : (object)it).ToArray(), type)); else if (childType == UtilConstants.BoolType) result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToBool()).ToArray(), type)); else if (childType == UtilConstants.ByteType) result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? 0 : (byte)it).ToArray(), type)); else if (childType == UtilConstants.DecType) result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToDecimal()).ToArray(), type)); else if (childType == UtilConstants.GuidType) result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? Guid.Empty : (Guid)it).ToArray(), type)); else if (childType == UtilConstants.DateType) result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? DateTime.MinValue : (DateTime)it).ToArray(), type)); else if (childType == UtilConstants.IntType) result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToInt()).ToArray(), type)); else Check.Exception(true, ErrorMessage.NotSupportedArray); } protected List GetValueTypeList(Type type, IDataReader dataReader) { List result = new List(); while (dataReader.Read()) { GetValueTypeList(type, dataReader, result); } return result; } protected async Task> GetValueTypeListAsync(Type type, IDataReader dataReader) { List result = new List(); while (await ((DbDataReader)dataReader).ReadAsync()) { GetValueTypeList(type, dataReader, result); } return result; } private static void GetValueTypeList(Type type, IDataReader dataReader, List result) { var value = dataReader.GetValue(0); if (type == UtilConstants.GuidType) { value = Guid.Parse(value.ToString()); } if (value == DBNull.Value) { result.Add(default(T)); } else if (type.IsEnum) { result.Add((T)Enum.Parse(type, value.ObjToString())); } else if (value!=null&&UtilMethods.GetUnderType(type).IsEnum) { result.Add((T)Enum.Parse(UtilMethods.GetUnderType(type), value.ObjToString())); } else { result.Add((T)UtilMethods.ChangeType2(value, type)); } } } }