我們經常需要從數據庫表中取數,取數是以取DataTable的方式,但是我么希望以對象為單位進行這種操作。即存在把取到的DataTable(數據表)轉換為ModelList(對象集合)的需求。
原理稍微復雜,因此我畫了一下:
這是DataSet中的DataTable
這是DataTable如何轉換成ModelList(對象集合),這樣我們就能從對象集合里取到對應對象來以對象為單位進行傳數
完成此功能需要以下函數:
返回DataTable具體位置的值時需要 NvlReturn函數,這里寫了四種,邏輯是判斷某個值是否為空值,若不為空值則輸出,若為空值,返回指定值(Int Long String Double四種類型)
Int類型
public static int NvlReturnInt(object obj)
{
try
{
if (obj != null) return obj.ToString().Length == 0 ? 0 : Convert.ToInt32(obj);
return 0;
}
catch
{
return 0;
}
}
Long類型
public static long NvlReturnLong(object obj)
{
try
{
if (obj != null)
return obj.ToString().Length == 0 ? 0 : Convert.ToInt64(obj);
return 0;
}
catch
{
return 0;
}
}
String類型
public static string NvlReturnString(object strObject, bool blTrim = false, bool blUpper = false)
{
try
{
if (strObject == null) return string.Empty;
var returnString = strObject.ToString();
if (blTrim) returnString = returnString.Trim();
if (blUpper) returnString = returnString.ToUpper();
return returnString;
}
catch
{
return string.Empty;
}
}
Double類型
public static double NvlReturnDouble(object obj)
{
try
{
if (obj != null) return obj.ToString().Length == 0 ? 0 : Convert.ToDouble(obj);
return 0;
}
catch
{
return 0;
}
}
把DataTable表的每一行轉換成一個對象,這需要我們把每一行的每一個位置一個個輸入對象的屬性,類似把一個二維表(DataTable)輸入一個一維表(對象)的集合,這個表轉換成為一個對象的集合,傳入的表在這里被稱為ThisTable
public static List<T> ConvertDataTableToModel<T>(DataTable ThisTable)
{
//使用typeof運算符來獲取Type對象,只需要提供類型名作為操作數,會返回Type對象的引用
//var ModelType = typeof運算(XXXClass)希望的Type對象類型;
var ModelType = typeof(T);
if (ThisTable == null || ThisTable.Rows.Count == 0)
return null;
var ModelList = new List<T>();
var DataRowCollection = ThisTable.Rows;
var DataColumnCollection = ThisTable.Columns;
//兩層循環來遍歷這個二維數組
//第一層循環,循環行
foreach (DataRow DR in DataRowCollection)//DataRow類的DR表示 DataTable 中的一行數據。
{
var a = DR[ThisTable.Columns[0]];//a是這個這么多行里的一行,並且每次循環會換一下(相當於各個行組成個數組,a是i,++a)
var Model = ModelType.Assembly.CreateInstance(ModelType.FullName);//從此程序集中查找某個類型,然后使用系統激活器創建它的實例。FullName獲取該類型的完全限定名稱,包括其命名空間,但不包括程序集
//第二層循環,循環每行中的屬性
foreach (var p in Model.GetType().GetProperties())//GetType得到運行時的類,GetProperties返回這個類的所有公共屬性。在這一行a中,p是這個屬性里的一項,並且每次循環會換一下(相當於屬性組成個數組,p是i,++p)
{
if (DR[DataColumnCollection[p.Name]] is DBNull)//Name獲取當前成員的名稱。p.Name就是當前行當前列的屬性名
{
p.SetValue(Model, null);
}
else
{
switch (p.PropertyType.Name)//switch(p這個屬性的.屬性類型.屬性類型名)
{
case "Int":
p.SetValue(Model, PubFunc.NvlReturnInt(DR[DataColumnCollection[p.Name]]));
break;
case "Long":
p.SetValue(Model, PubFunc.NvlReturnLong(DR[DataColumnCollection[p.Name]]));
break;
case "String":
p.SetValue(Model, PubFunc.NvlReturnString(DR[DataColumnCollection[p.Name]]));
break;
case "Double":
p.SetValue(Model, PubFunc.NvlReturnDouble(DR[DataColumnCollection[p.Name]]));
break;
default:
p.SetValue(Model, null);
break;
}
}
ModelList.Add((T)Model);
}
}
return ModelList;
}
使用注意!使用注意!使用注意!使用注意!使用注意!使用注意!
首先,要求數據庫中你使用的這張數據表的各個字段,與你要轉換成類的類型完全相同,即你的表中字段的名字要與你定義的類的屬性一一對應。
舉例:(我特意定義了一個數據庫中表傳數據專用的類(TableInfo),來實現字段與屬性的一一對應)
這里是Sqlite可視化應用里顯示的數據庫表結構
這里是Model層定義的專用類(TableInfo)
這里sqlite數據庫表中的字段與專用類(TableInfo)中的屬性必須一一對應!
我原本用來作為傳輸單位的類(UserInfo)結構比這個特地定義的數據庫中表傳數據專用的類(TableInfo)包含的屬性多一些
然后調用時候的方式是這樣的
這個函數返回true,在UI層就可以接收到true的返回值
程序會彈出 登錄成功!