You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

277 lines
11 KiB

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
{
/// <summary>
/// 将DataReader数据转为Dynamic对象
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static dynamic DataFillDynamic(IDataReader reader)
{
using (reader)
{
dynamic d = new ExpandoObject();
for (int i = 0; i < reader.FieldCount; i++)
{
try
{
((IDictionary<string, object?>)d).Add(reader.GetName(i), reader.GetValue(i));
}
catch
{
((IDictionary<string, object?>)d).Add(reader.GetName(i), null);
}
}
return d;
}
}
/// <summary>
/// 获取模型对象集合
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public static List<dynamic> DataFillDynamicList(IDataReader reader)
{
using (reader)
{
List<dynamic> list = new List<dynamic>();
if (reader != null && !reader.IsClosed)
{
while (reader.Read())
{
list.Add(DataFillDynamic(reader));
}
reader.Close();
reader.Dispose();
}
return list;
}
}
/// <summary>
/// 将IDataReader转换为集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reader"></param>
/// <returns></returns>
public static List<T> IDataReaderToList<T>(IDataReader reader)
{
using (reader)
{
List<string> field = new List<string>(reader.FieldCount);
for (int i = 0; i < reader.FieldCount; i++)
{
field.Add(reader.GetName(i).ToLower());
}
List<T> list = new List<T>();
while (reader.Read())
{
T model = Activator.CreateInstance<T>();
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;
}
}
/// <summary>
/// 将IDataReader转换为DataTable
/// </summary>
/// <param name="dr"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 获取实体类键值(缓存)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>
/// <returns></returns>
public static Hashtable GetPropertyInfo<T>(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<T> AppendSort<T>(IQueryable<T> 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<T>(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;
}
/// <summary>
/// 获取使用Linq生成的Sql
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="query"></param>
/// <returns></returns>
//public static string GetSql<TEntity>(this IQueryable<TEntity> query)
//{
// var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
// var relationalCommandCache = enumerator.Private("_relationalCommandCache");
// var selectExpression = relationalCommandCache.Private<SelectExpression>("_selectExpression");
// var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");
// var sqlGenerator = factory.Create();
// var command = sqlGenerator.GetCommand(selectExpression);
// string sql = command.CommandText;
// return sql;
//}
/// <summary>
/// 获取运行时的Sql
/// </summary>
/// <param name="dbCommand"></param>
/// <returns></returns>
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<T>(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj)!;
#endregion
}
}