using Serilog; using System.Collections; using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; using System.Data; using System.Data.Common; using System.Dynamic; using System.Linq.Expressions; using System.Reflection; using Wood.Util; namespace Wood.Data.Repository { public static class DatabasesExtension { /// /// 将DataReader数据转为Dynamic对象 /// /// /// public static dynamic DataFillDynamic(IDataReader reader) { using (reader) { dynamic d = new ExpandoObject(); for (int i = 0; i < reader.FieldCount; i++) { try { ((IDictionary)d).Add(reader.GetName(i), reader.GetValue(i)); } catch { ((IDictionary)d).Add(reader.GetName(i), null); } } return d; } } /// /// 获取模型对象集合 /// /// /// public static List DataFillDynamicList(IDataReader reader) { using (reader) { List list = new List(); if (reader != null && !reader.IsClosed) { while (reader.Read()) { list.Add(DataFillDynamic(reader)); } reader.Close(); reader.Dispose(); } return list; } } /// /// 将IDataReader转换为集合 /// /// /// /// public static List IDataReaderToList(IDataReader reader) { using (reader) { List field = new List(reader.FieldCount); for (int i = 0; i < reader.FieldCount; i++) { field.Add(reader.GetName(i).ToLower()); } List list = new List(); while (reader.Read()) { T model = Activator.CreateInstance(); if (model != null) { var properties = ReflectionHelper.GetProperties(model.GetType()); if (properties != null) { foreach (PropertyInfo property in properties) { if (field.Contains(property.Name.ToLower())) { if (!IsNullOrDBNull(reader[property.Name])) { property.SetValue(model, HackType(reader[property.Name], property.PropertyType), null); } } } } list.Add(model); } } reader.Close(); reader.Dispose(); return list; } } /// /// 将IDataReader转换为DataTable /// /// /// public static DataTable IDataReaderToDataTable(IDataReader reader) { using (reader) { DataTable objDataTable = new DataTable("Table"); int intFieldCount = reader.FieldCount; for (int intCounter = 0; intCounter < intFieldCount; ++intCounter) { objDataTable.Columns.Add(reader.GetName(intCounter).ToLower(), reader.GetFieldType(intCounter)); } objDataTable.BeginLoadData(); object[] objValues = new object[intFieldCount]; while (reader.Read()) { reader.GetValues(objValues); objDataTable.LoadDataRow(objValues, true); } reader.Close(); reader.Dispose(); objDataTable.EndLoadData(); return objDataTable; } } /// /// 获取实体类键值(缓存) /// /// /// /// public static Hashtable GetPropertyInfo(T entity) { Hashtable ht = new Hashtable(); PropertyInfo[]? props = ReflectionHelper.GetProperties(entity!.GetType()); if (props != null) { foreach (PropertyInfo prop in props) { bool flag = true; foreach (Attribute attr in prop.GetCustomAttributes(true)) { NotMappedAttribute? notMapped = attr as NotMappedAttribute; if (notMapped != null) { flag = false; break; } } if (flag) { string name = prop.Name; object? value = prop?.GetValue(entity, null); ht[name] = value; } } } return ht; } public static IQueryable AppendSort(IQueryable tempData, string sort, bool isAsc) { string[] sortArr = sort.Split(','); MethodCallExpression? resultExpression = null; for (int index = 0; index < sortArr.Length; index++) { string[] oneSortArr = sortArr[index].Trim().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); string sortField = oneSortArr[0]; bool sortAsc = isAsc; if (oneSortArr.Length == 2) { sortAsc = string.Equals(oneSortArr[1], "asc", StringComparison.OrdinalIgnoreCase) ? true : false; } var parameter = Expression.Parameter(typeof(T), "t"); var property = ReflectionHelper.GetProperties(typeof(T))!.Where(p => p.Name.ToLower() == sortField.ToLower()).FirstOrDefault(); var propertyAccess = Expression.MakeMemberAccess(parameter, property!); var orderByExpression = Expression.Lambda(propertyAccess, parameter); if (index == 0) { resultExpression = Expression.Call(typeof(Queryable), sortAsc ? "OrderBy" : "OrderByDescending", new Type[] { typeof(T), property!.PropertyType }, tempData.Expression, Expression.Quote(orderByExpression)); } else { resultExpression = Expression.Call(typeof(Queryable), sortAsc ? "ThenBy" : "ThenByDescending", new Type[] { typeof(T), property!.PropertyType }, tempData.Expression, Expression.Quote(orderByExpression)); } tempData = tempData.Provider.CreateQuery(resultExpression); } return tempData; } //这个类对可空类型进行判断转换,要不然会报错 public static object? HackType(object value, Type conversionType) { if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { if (value == null) return null; NullableConverter nullableConverter = new NullableConverter(conversionType); conversionType = nullableConverter.UnderlyingType; } return Convert.ChangeType(value, conversionType); } public static bool IsNullOrDBNull(object obj) { return ((obj is DBNull) || string.IsNullOrEmpty(obj.ToString())) ? true : false; } /// /// 获取使用Linq生成的Sql /// /// /// /// //public static string GetSql(this IQueryable query) //{ // var enumerator = query.Provider.Execute>(query.Expression).GetEnumerator(); // var relationalCommandCache = enumerator.Private("_relationalCommandCache"); // var selectExpression = relationalCommandCache.Private("_selectExpression"); // var factory = relationalCommandCache.Private("_querySqlGeneratorFactory"); // var sqlGenerator = factory.Create(); // var command = sqlGenerator.GetCommand(selectExpression); // string sql = command.CommandText; // return sql; //} /// /// 获取运行时的Sql /// /// /// public static string GetCommandText(this DbCommand dbCommand) { var sql = dbCommand.CommandText; foreach (DbParameter parameter in dbCommand.Parameters) { try { string? value = string.Empty; switch (parameter.DbType) { case DbType.Date: value = parameter.Value?.ToString()?.ToDateTime()?.ToString("yyyy-MM-dd HH:mm:ss"); break; default: value = parameter.Value?.ToString(); break; } sql = sql.Replace(parameter.ParameterName, value); } catch (Exception ex) { Log.Error(ex, "获取SQL语句时,组装sqlparameter参数失败:sql({sql}),DbType({DbType}),ParameterName({ParameterName}),ParameterValue({ParameterValue})",sql,parameter.DbType.ToString(), parameter.ParameterName, parameter.Value?.ToString()); } } return sql; } #region 私有方法 private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)!; private static T Private(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)!; #endregion } }