Reflection應用於Linq更新
- 2850
- 3
demo在今天(現在是凌晨應該是說昨天)撰寫案子的時候遇到了一個問題,一個資料表中有超過30個欄位,因為現在demo都是用Linq在操作資料庫了,之前寫的時候也沒啥問題,但是這次的30個欄位難道我要和白癡一樣一行一行寫嗎?心中的OS:「程式不該是這樣」,想了一下呼叫了召喚獸,召喚獸給了一個關鍵字Reflection。
- 檔案名稱:Reflection
什麼是Reflection?Reflection字面上翻譯就是反映、反射的意思,在.Net內的Reflection很有趣,通常我們會知道一個物件的存在會順便知道它的型別屬性啥鬼的,但是有些時候我們只會知道有這個型別會在這裡用,不知道它會有什麼方法、欄位、屬性的時候就可以利用Reflection反推回去,是一個誇張方便的東西它的用處多多,demo也還沒完全掌握,所以更深入的介紹也不適合在這班門弄斧,這玩意是好物多多利用吧MSDN
好,回到主題以往我們使用Linq來做更新的時候你可能會這樣寫
var oldData=(from p in db.下拉清單 where p.ID==id select p).FirstOrDefault(); oldData.OO = ""; oldData.XX = ""; db.SubmitChanges();
很正常也很自然,但是當你遇到了10個欄位要更新呢?
var oldData=(from p in db.下拉清單 where p.ID==id select p).FirstOrDefault(); oldData.AA = ""; oldData.BB = ""; oldData.CC = ""; oldData.DD = ""; /*…………………*/ oldData.II = ""; db.SubmitChanges();
好,10個解決了那30個?50個?也都是這樣這寫嗎?,俗話說的好程式設計師就是要懶!!不懶就不會寫出更精簡的Code所以demo利用了Reflection的特性來去做了一件簡單的事情
//這是傳來要更新的物件
DemandSschedule.Models.OOXX newData
//這裡是抓出資料庫原有物件
var dbData=(from p in db.OOXX where p.ID==id select p).FirstOrDefault();
/*以下這段code就動用到了 Reflection Linq部份預設你看得懂了,所以白話的翻譯就是
* 我利用newData的型別找到所有的屬性集合並且轉型為屬性敘述
* 過濾掉名稱為ID的
*/
var t = from p in TypeDescriptor.GetProperties(newData).Cast<PropertyDescriptor>()
where p.Name != "ID"
select p;
foreach (var item in t)
{
//這段忽然看可能會亂,多看幾次就懂了
item.SetValue(dbData, item.GetValue(newData));
}
db.SubmitChanges();
這樣子你就可以看到威力了,不管我在OOXX裡面是有多少欄位都會更新了,完全不用去指定欄位,它就可以自己抓,那你可能又會說我要大量更新呢?很簡單阿Linq語法改一下不要去where ID再多跑一個迴圈就成了。
DemandSschedule.Models.OOXX newData
var dbData=(from p in db.OOXX select p).ToArray();
var t = from p in TypeDescriptor.GetProperties(newData).Cast<PropertyDescriptor>()
where p.Name != "ID"
select p;
foreach (var item in t)
{
for (int i = 0; i < dbData.Length; i++)
{
item.SetValue(dbData[i], item.GetValue(newData));
}
}
db.SubmitChanges();
這樣子的Code看起來就是爽!!
這一個小小的例子我們就可以發現Reflection的好用了,有很多之前不知道怎麼搞的部份都有解了,所以這項技能記得要點阿。

網友回應
- digitalwow

- 發表於: 2009-10-06
- 不錯用法..如果30個欄位...實際上只有10個要改變..其它不變...是否其它20個會變成null 或空值呢.
-
你可以利用
- if (item.GetValue(newData) != null)
- item.SetValue(dbData, item.GetValue(newData));
來過濾掉null的值也可以在最上面的
- where p.Name != "ID"
增加一些絕對不要被更新的欄位
回覆於: 2009-10-07
- aliku

- 發表於: 2009-05-20
- 請問那要給欄位的"值"是在哪給的呢?? 若說有30個欄位要更新, 這30個值是在哪一個階段給呢?? 不用一個一個欄位對應給嗎?? 因範例看不到新的"值"在哪? 謝謝!!
-
item.SetValue(dbData, item.GetValue(newData));
回覆於: 2009-05-21
這一段的 item.GetValue(newData) 就是"值"了,因為你要更新的一定是相同欄位名稱吧,所以
var t = from p in TypeDescriptor.GetProperties(newData).Cast<PropertyDescriptor>()
where p.Name != "ID"
select p;
這一段抓出來的 t 就是新資料了,利用映射就自然的對應到欄位去
- Bibby

- 發表於: 2009-03-01
- 不過效率不是很好..^^..算缺點ㄅ..
-
並不會不好阿
回覆於: 2009-03-01