DataTable數據集轉換為List非泛型以及泛型方式


前言

DataTable是斷開式的數據集合,所以一旦從數據庫獲取,就會在內存中創建一個數據的副本,以便使用。由於在實際項目中,經常會將DataTable中的每行數據轉換為Model,然后放到List集合中,所以,下面提供了轉換的兩種思路:非泛型轉換思路和泛型轉換思路。

非泛型方式

首先來說下非泛型轉換,這種轉換方式就是通過遍歷DataTable,然后向Model中的相同字段中賦值即可。

 //使用Linq的ToList方法,非泛型
        public static List<Entity> ConvertTo(DataTable dt)
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<Entity> list = new List<Entity>();
            list = (from DataRow dr in dt.Rows
                    select new Entity
                    {
                        PID = Int32.Parse(dr["PID"].ToString()),
                        PName = dr["PName"].ToString(),
                        PPass = dr["PPass"].ToString(),
                        PAddr = dr["PAddr"].ToString()
                    }).ToList();
            return list;
        }

代碼很簡單,就是通過循環賦值而已。這里我用的Model測試類如下:

 
namespace DataSetToEntity.Code
{
    public class Entity
    {
        public int PID { get; set; }
 
        public string PName { get; set; }
 
        public string PPass { get; set; }
 
        public string PAddr { get; set; }
    }
}

泛型方式

然后,由於非泛型的版本不具有通用性,所以這里我們准備用泛型版本來實現一下,由於泛型版本是不可預知Model中的屬性結構的,所以這里我們需要引入反射來進行操作。

//使用反射的泛型方法一
        public static List<T> ConvertTo<T>(DataTable dt) where T : new()
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<T> list = new List<T>();
            try
            {
                List<string> columnsName = new List<string>();  
                foreach (DataColumn dataColumn in dt.Columns)
                {
                    columnsName.Add(dataColumn.ColumnName);//得到所有的表頭
                }
                list = dt.AsEnumerable().ToList().ConvertAll<T>(row => getObject<T>(row, columnsName));  //轉換
                return list;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
 
        public static T getObject<T>(DataRow row, List<string> columnsName) where T : new()
        {
            T obj = new T();
            try
            {
                string columnname = "";
                string value = "";
                PropertyInfo[] Properties = typeof(T).GetProperties();
                foreach (PropertyInfo objProperty in Properties)  //遍歷T的屬性
                {
                    columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower()); //尋找可以匹配的表頭名稱
                    if (!string.IsNullOrEmpty(columnname))
                    {
                        value = row[columnname].ToString();
                        if (!string.IsNullOrEmpty(value))
                        {
                            if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null) //存在匹配的表頭
                            {
                                value = row[columnname].ToString().Replace("$", "").Replace(",", ""); //從dataRow中提取數據
                                objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null); //賦值操作
                            }
                            else
                            {
                                value = row[columnname].ToString().Replace("%", ""); //存在匹配的表頭
                                objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null);//賦值操作
                            }
                        }
                    }
                }
                return obj;
            }
            catch
            {
                return obj;
            }
        }
 
上面主要是通過反射獲取T的屬性名稱,然后和DataRow中的表頭相匹配,如果匹配的上,就賦值。下面是其簡化版本:
 
//使用反射的泛型方法二
        public static List<T> ConvertToEx<T>(DataTable dt) where T : new()
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<T> list = new List<T>();
            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties();  //獲取泛型的屬性
            List<DataColumn> listColumns = dt.Columns.Cast<DataColumn>().ToList();  //獲取數據集的表頭,以便於匹配
            T t;
            foreach (DataRow dr in dt.Rows)   
            {
                t = new T();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    try
                    {
                        DataColumn dColumn = listColumns.Find(name => name.ToString().ToUpper() == propertyInfo.Name.ToUpper());  //查看是否存在對應的列名
                        if (dColumn != null)
                            propertyInfo.SetValue(t, dr[propertyInfo.Name], null);  //賦值
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                }
                list.Add(t);
            }
            return list;
        }
 
至於使用方式,很簡單,直接利用下面的代碼即可:
 List<Entity> list = CommonUtils.ConvertToEx<Entity>(dt);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM