ZhiYeJianKang_PeiXun/cyqdata-master/Tool/Convert/ConvertTool.ChangeReaderToList.cs

253 lines
11 KiB
C#
Raw Normal View History

2025-02-20 15:41:53 +08:00
using CYQ.Data.Json;
using CYQ.Data.SQL;
using CYQ.Data.Table;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlTypes;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Web;
namespace CYQ.Data.Tool
{
/// <summary>
/// 类型转换支持json转实体
/// </summary>
public static partial class ConvertTool
{
/// <summary>
/// DbDataReader To List
/// </summary>
internal static List<T> ChangeReaderToList<T>(DbDataReader reader)
{
Type t = typeof(T);
List<T> list = new List<T>();
if (t.Name == "MDataRow")
{
MDataTable dt = reader;
foreach (object row in dt.Rows)
{
list.Add((T)row);
}
}
else if (reader != null)
{
#region Reader
if (reader.HasRows)
{
Dictionary<string, Type> kv = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < reader.FieldCount; i++)
{
string key = reader.GetName(i);
if (!kv.ContainsKey(key))//ado.net 底层bug特殊情况会读出多余重复字段结构https://q.cnblogs.com/q/143699/
{
kv.Add(key, reader.GetFieldType(i));
}
}
List<PropertyInfo> pInfoList = ReflectTool.GetPropertyList(t);
List<FieldInfo> fInfoList = ReflectTool.GetFieldList(t);
//SQLite 报错:该字符串未被识别为有效的 DateTime不能用sr[类型读]要用sdr.GetString读
// List<string> errIndex = new List<string>();//SQLite提供的dll不靠谱sdr[x]类型转不过时,会直接抛异常
Dictionary<string, int> errIndex = new Dictionary<string, int>();
while (reader.Read())
{
T obj = Activator.CreateInstance<T>();
if (pInfoList.Count > 0)
{
foreach (PropertyInfo p in pInfoList)//遍历实体
{
if (p.CanWrite && kv.ContainsKey(p.Name))
{
object objValue = null;
try
{
if (errIndex.ContainsKey(p.Name))
{
int index = errIndex[p.Name];
if (!reader.IsDBNull(index))
{
objValue = reader.GetString(index);
}
}
else
{
objValue = reader[p.Name];
}
}
catch
{
int index = reader.GetOrdinal(p.Name);
if (!errIndex.ContainsKey(p.Name))
{
errIndex.Add(p.Name, index);
}
objValue = reader.GetString(index);
}
if (objValue != null && objValue != DBNull.Value)
{
if (p.PropertyType != kv[p.Name] || errIndex.ContainsKey(p.Name))
{
objValue = ChangeType(objValue, p.PropertyType);//尽量避免类型转换
}
p.SetValue(obj, objValue, null);
}
}
}
}
if (fInfoList.Count > 0)
{
foreach (FieldInfo f in fInfoList)//遍历实体
{
if (kv.ContainsKey(f.Name))
{
object objValue = null;
try
{
if (errIndex.ContainsKey(f.Name))
{
objValue = reader.GetString(errIndex[f.Name]);
}
else
{
objValue = reader[f.Name];
}
}
catch
{
int index = reader.GetOrdinal(f.Name);
errIndex.Add(f.Name, index);
objValue = reader.GetString(index);
}
if (objValue != null && objValue != DBNull.Value)
{
if (f.FieldType != kv[f.Name] || errIndex.ContainsKey(f.Name))
{
objValue = ChangeType(objValue, f.FieldType);//尽量避免类型转换
}
f.SetValue(obj, objValue);
}
}
}
}
list.Add(obj);
}
kv.Clear();
kv = null;
errIndex.Clear();
errIndex = null;
}
reader.Close();
reader.Dispose();
reader = null;
#endregion
}
return list;
//return List<default(T)>;
}
/// <summary>
/// DbDataReader To Json
/// </summary>
internal static string ChangeReaderToJson(DbDataReader reader, JsonHelper js, bool needCheckHiddenField)
{
if (js == null)
{
js = new JsonHelper(false, false);
}
if (reader != null)
{
bool[] isBool = new bool[reader.FieldCount];
bool[] isDateTime = new bool[reader.FieldCount];
bool[] isNoQuotes = new bool[reader.FieldCount];
bool[] isHiddenField = new bool[reader.FieldCount];
string hiddenFields = "," + AppConfig.DB.HiddenFields.ToLower() + ",";
for (int i = 0; i < reader.FieldCount; i++)
{
if (needCheckHiddenField)
{
isHiddenField[i] = hiddenFields.IndexOf("," + reader.GetName(i) + ",", StringComparison.OrdinalIgnoreCase) > -1;
}
switch (DataType.GetGroup(DataType.GetSqlType(reader.GetFieldType(i))))
{
case DataGroupType.Bool:
isBool[i] = true;
isNoQuotes[i] = true;
break;
case DataGroupType.Number:
isNoQuotes[i] = true;
break;
case DataGroupType.Date:
isDateTime[i] = true;
break;
}
}
#region Reader
//SQLite 报错:该字符串未被识别为有效的 DateTime不能用sr[类型读]要用sdr.GetString读
// List<string> errIndex = new List<string>();//SQLite提供的dll不靠谱sdr[x]类型转不过时,会直接抛异常
bool[] errIndex = new bool[reader.FieldCount];
if (reader.HasRows)
{
while (reader.Read())
{
js.RowCount++;
for (int i = 0; i < reader.FieldCount; i++)
{
if (isHiddenField[i]) { continue; }
object objValue = null;
try
{
if (errIndex[i])
{
objValue = reader.GetString(i);
}
else
{
objValue = reader.GetValue(i);
}
}
catch
{
errIndex[i] = true;
objValue = reader.GetString(i);
}
if (isDateTime[i])
{
DateTime dt;
if (DateTime.TryParse(Convert.ToString(objValue), out dt))
{
objValue = dt.ToString(js.DateTimeFormatter);
}
}
else if (isBool[i])
{
objValue = objValue.ToString().ToLower();
}
js.Add(reader.GetName(i), Convert.ToString(objValue), isNoQuotes[i]);
}
js.AddBr();
}
}
reader.Close();
reader.Dispose();
reader = null;
#endregion
}
return js.ToString();
}
}
}