技術(shù)圖文:如何實(shí)現(xiàn) DataTable 與模型類 List 的相互轉(zhuǎn)換?

通常情況下,我們?cè)谧龉こ添?xiàng)目的時(shí)候,需要把待處理的數(shù)據(jù)存儲(chǔ)在數(shù)據(jù)庫(kù)中。

通過 SQLSelect 語句很容易把查詢的結(jié)果以 DataTable 的方式得到,但在對(duì) DateTable 中的數(shù)據(jù)進(jìn)行進(jìn)一步的檢索時(shí)遠(yuǎn)遠(yuǎn)沒有模型類 List<T> 方便。 所以,在做工程項(xiàng)目時(shí),會(huì)把查詢到的 DataTable 轉(zhuǎn)化成模型類 List<T>, 處理完畢后如果有所改動(dòng)則把這個(gè)模型類 換回成 DataTable 以便完成數(shù)據(jù)庫(kù)中的相應(yīng)改動(dòng)。

上周在做一個(gè)電力局項(xiàng)目時(shí)對(duì)導(dǎo)入的上萬條數(shù)據(jù)進(jìn)行插入操作就是這樣做的,參見一下圖文:


技術(shù)分析

如何實(shí)現(xiàn) DataTableList<T> 的相互轉(zhuǎn)化呢?

這里需要掌握 C# 中的 泛型 以及 反射 的基礎(chǔ)知識(shí)。

泛型部分:

反射部分:

通過泛型,我們可以把任何一個(gè)模型類 List<T> 轉(zhuǎn)化成 DataTable,也可以把任何一個(gè) DataTable 轉(zhuǎn)化成對(duì)應(yīng)的 List<T>,只要這里 T 類型的 public 屬性DataTableColumnName 對(duì)應(yīng)即可。當(dāng)然屬性的獲取是通過反射技術(shù)完成的。

有關(guān)泛型和反射的知識(shí),可以查看上面的圖文,我在這里就不在重復(fù)了。


代碼實(shí)現(xiàn)

下面,通過一個(gè)實(shí)際項(xiàng)目的例子來說明相互轉(zhuǎn)換的代碼與具體的應(yīng)用。

Step1. 設(shè)備臺(tái)賬的結(jié)構(gòu) AcountItem。

/// <summary>
/// 臺(tái)賬Item
/// </summary>
public class AccountItem
{
    /// <summary>
    /// 設(shè)備ID
    /// </summary>
    public string EquipmentId
    {
        get;
        set; 
    }
    /// <summary>
    /// 廠站名稱
    /// </summary>
    public string FactoryStationName
    {
        get;
        set; 
    }
    /// <summary>
    /// 廠站類型
    /// </summary>
    public string FactoryStationType
    {
        get;
        set; 
    }
    /// <summary>
    /// 一次設(shè)備名稱
    /// </summary>
    public string PrimaryDeviceName 
    { get; set; }
    /// <summary>
    /// 一次設(shè)備電壓等級(jí)
    /// </summary>
    public string PrimaryDeviceVoltageLevel 
    { get; set; }
    /// <summary>
    /// 制造廠家
    /// </summary>
    public string Manufacturer 
    { 
        get;
        set; 
    }
    /// <summary>
    /// 保護(hù)類別
    /// </summary>
    public string ProtectionCategory 
    {
        get;
        set;   
    }
    /// <summary>
    /// 保護(hù)型號(hào)
    /// </summary>
    public string ProtectionType 
    {
        get;
        set; 
    }
    /// <summary>
    /// 軟件版本
    /// </summary>
    public string SoftwareVersion 
    { 
        get;
        set; 
    }
    /// <summary>
    /// 保護(hù)名稱
    /// </summary>
    public string ProtectionName 
    {
        get;
        set; 
    }
    /// <summary>
    /// 投運(yùn)日期
    /// </summary>
    public string CommissionDate 
    {
        get;
        set; 
    }
    /// <summary>
    /// 出廠日期
    /// </summary>
    public string ProductionDate 
    {
        get;
        set; 
    }
    /// <summary>
    /// 所在屏柜
    /// </summary>
    public string ScreenCabinets 
    {
        get;
        set; 
    }
    /// <summary>
    /// 保護(hù)套別
    /// </summary>
    public string ProtectiveSleeve 
    {
        get;
        set; 
    }
}

Step2. 把模型類 List<T> 轉(zhuǎn)化為 DataTable。

public static DataTable ListToDataTable<T>(IEnumerable<T> collection)
{
    if (collection == null)
        throw new ArgumentNullException();

    PropertyInfo[] props = typeof (T).GetProperties();
    DataTable dt = new DataTable();
    dt.Columns.AddRange(props.Select(
            p => new DataColumn(p.Name, p.PropertyType)
        ).ToArray());
    if (collection.Any())
    {
        for (int i = 0; i < collection.Count(); i++)
        {
            ArrayList tempList = new ArrayList();
            foreach (PropertyInfo pi in props)
            {
                object obj = pi.GetValue(collection.ElementAt(i), null);
                tempList.Add(obj);
            }
            object[] array = tempList.ToArray();
            dt.LoadDataRow(array, true);
        }
    }
    return dt;
}

Step3. 舉例,把 List<AcountItem> 轉(zhuǎn)化為 DataTable。

// 初始化鏈表并加入數(shù)據(jù)。
List<AccountItem> lst = new List<AccountItem>(); 

DataTable dt = ListToDataTable(lst);

dt 數(shù)據(jù)表列集合的列名依次為:

  • EquipmentId
  • FactoryStationName
  • FactoryStationType
  • PrimaryDeviceName
  • PrimaryDeviceVoltageLevel
  • Manufacturer
  • ProtectionCategory
  • ProtectionType
  • SoftwareVersion
  • ProtectionName
  • CommissionDate
  • ProductionDate
  • ScreenCabinets
  • ProtectiveSleeve;

Step4. DataTable 轉(zhuǎn)化為 List<T>。

public static List<T> DataTableToList<T>(DataTable dt) where T : new()
{
    List<T> result = new List<T>();
    foreach (DataRow dr in dt.Rows)
    {
        T item = new T();
        PropertyInfo[] props = item.GetType().GetProperties();
        foreach (PropertyInfo pi in props)
        {
            string tempName = pi.Name;
            if (dt.Columns.Contains(tempName))
            {
                if (pi.CanWrite == false)
                    continue;

                object value = dr[tempName];
                if (value != DBNull.Value)
                    pi.SetValue(item, value, null);
            }
        }
        result.Add(item);
    }
    return result;
}

Step5. 舉例,把 Step3 得到的 DataTable 轉(zhuǎn)化為 List<AccountItem>。

List<AccountItem> lst = DataTableToList(dt);

通過調(diào)用 Step4 帶約束的泛型方法,可以得到模型類 List<AccountItem>。


總結(jié)

到此為止,DataTableList<T> 的相互轉(zhuǎn)換就介紹完了,由于整個(gè)項(xiàng)目都是利用 List<T> 來構(gòu)建邏輯的,所以整個(gè)系統(tǒng)可以具有良好的結(jié)構(gòu),通過 LINQ 也能滿足效率的要求。今天就到這里吧!See You!


相關(guān)圖文

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容