C# LINQ TO SQL 利用反映(Reflection)達到動態更新

摘要: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)取得不同資料物件屬性