摘要:C# LINQ TO SQL 利用反映(Reflection)達到動態更新
我相信網路上很多前輩已經將Reflection(反射應用)講解得很好,
我在這裡剛好實務上有需求,做個筆記,怕會忘記!.如果前輩有更好的建議.
也請不吝指導~
需求:
近來有一個功能,算是一個很簡單的更新(update)會員資料,
利用WEBAPI依照傳進來的參數,來決定要更新哪個欄位,
當然如果在程式裡面下組SQL command 當然是很快.
但使用的是Linq To SQL的架構,
所以在實作上就會有所不同嚕
解決方案:
這時候就很感謝網路上,各位前輩無私的方享了!有了一個方向.利用Reflection來達到動態更新.
這樣如果client 沒送出要更新暱稱或電話欄位,
server也不要逐一個變數去判斷有沒有值!!
實作:
首先先新增一個Class ,接收使用者傳進來的值
public class socialmember {
public string name
{
get
{
return _name;
}
set
{
_name = value;
}
}
private string _name = "";
public string nickname
{
get
{
return _nickname;
}
set
{
_nickname = value;
}
}
private string _nickname = "";
public string email
{
get
{
return _email;
}
set
{
_email = value;
}
}
private string _email = "";
public string birthday
{
get
{
return _birthday;
}
set
{
_birthday = value;
}
}
private string _birthday = "";
public string mobile
{
get
{
return _mobile;
}
set
{
_mobile = value;
}
}
private string _mobile = "";
//更新的動作
public JObject SocialUserInfoUpdate(string people_id)
{
JObject Rtval = new JObject();
SocialmemberDataContext uptpersonInfo = new SocialmemberDataContext();
try
{
//找出預更新的筆數
var updateSocialPersonInfo = from a in uptpersonInfo.biog_social
where a.people_id == people_id
select a;
//InparmRef利用typeof找出此socialmember class中<請參考圖一,圖二>,
//傳進來所定義公開的變數
//並透過LINQ排除不需要的變數
IEnumerable InparmRef = typeof(socialmember).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(w => w.Name != "apikey" && w.Name != "action");
foreach (biog_social bis in updateSocialPersonInfo)
{
//在此逐一取出所傳進來的參數
foreach (var item in InparmRef)
{
//取得socialmember class中變數名稱
string ControlName = item.Name;
//取得socialmember class中變數中的值
object GetInparmVal = item.GetValue(this);
string GetTypeStr = "";
string biog_socialCoulumeName = "";
//由這裡將socialmember class 取出的變數名稱,
//對應到biog_social MODEL中的欄位
switch (ControlName)
{
case "name":
biog_socialCoulumeName = "people_name";
break;
case "nickname":
biog_socialCoulumeName = "nick_name";
break;
case "email":
biog_socialCoulumeName = "email_addr";
break;
case "mobile":
biog_socialCoulumeName = "mobile";
break;
case "birthday":
biog_socialCoulumeName = "b_date";
break;
default:
break;
}
//透過Reflection取出biog_social MODEL中此TABLE的欄位
System.Reflection.PropertyInfo bisRef = typeof(biog_social).GetProperty(biog_socialCoulumeName);
//如果傳進來的參數有對應到biog_social中的欄位,
//bisRef就不會視為null值!
if (bisRef != null)
{
//GetTypeStr是為了取出目前MODEL中biog_social某個欄位的型態(System.String..or System.Int16...etc),
//是為了把傳進來的參數,確保跟MODEL的欄位是一樣的型態!
//下IIF判斷式是因為,如果在biog_social MODEL中該欄位為可NULL的時候,
//不會存在於PropertyType.FullName,
//而是存在於PropertyType.GenericTypeArguments之中屬於Type[] !請參考<圖三>
GetTypeStr = bisRef.PropertyType.GenericTypeArguments.Select(s => s.FullName).FirstOrDefault() == null ?
bisRef.PropertyType.FullName : bisRef.PropertyType.GenericTypeArguments.Select(s => s.FullName).FirstOrDefault();
//取得型態(System.String..or System.Int16...etc)
Type DymaticType = Type.GetType(GetTypeStr);
//將值轉型成符合MODEL欄位的屬性
object updateValue = Convert.ChangeType(GetInparmVal, DymaticType);
//將傳進來的參數值,合併到biog_social MODEL中的欄位
//請參考<圖四>
bisRef.SetValue(bis, updateValue);
}
}
}
//最後送出更新
uptpersonInfo.SubmitChanges();
Rtval = new JObject()
{
new JProperty("status","200"),
new JProperty("message","已更新")
};
}
catch (Exception e)
{
Rtval = new JObject()
{
new JProperty("status","401"),
new JProperty("message","Error")
};
}
uptpersonInfo.Connection.Close();
uptpersonInfo.Dispose();
return Rtval;
}
}
圖一.
圖二.
圖三
圖四.
參考連結
linq to sql only selecting data from columns in object that are not null
反映 (C# 和 Visual Basic)
C# - Reflection反射運用 Part 1 (Type.InvokeMember)取得不同資料物件屬性