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

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

通過 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ù)庫中的相應(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)系作者
  • 序言:七十年代末穆役,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梳凛,更是在濱河造成了極大的恐慌耿币,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件韧拒,死亡現(xiàn)場(chǎng)離奇詭異淹接,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)叛溢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門塑悼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人楷掉,你說我怎么就攤上這事厢蒜。” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵郭怪,是天一觀的道長(zhǎng)支示。 經(jīng)常有香客問我刊橘,道長(zhǎng)鄙才,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任促绵,我火速辦了婚禮攒庵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘败晴。我一直安慰自己浓冒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布尖坤。 她就那樣靜靜地躺著稳懒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪慢味。 梳的紋絲不亂的頭發(fā)上场梆,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音纯路,去河邊找鬼或油。 笑死,一個(gè)胖子當(dāng)著我的面吹牛驰唬,可吹牛的內(nèi)容都是我干的顶岸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叫编,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼辖佣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起搓逾,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤卷谈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后恃逻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雏搂,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年寇损,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凸郑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矛市,死狀恐怖芙沥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤而昨,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布救氯,位于F島的核電站,受9級(jí)特大地震影響歌憨,放射性物質(zhì)發(fā)生泄漏着憨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一务嫡、第九天 我趴在偏房一處隱蔽的房頂上張望甲抖。 院中可真熱鬧,春花似錦心铃、人聲如沸准谚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柱衔。三九已至,卻和暖如春愉棱,著一層夾襖步出監(jiān)牢的瞬間唆铐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工羽氮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留或链,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓档押,卻偏偏與公主長(zhǎng)得像澳盐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子令宿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容