2017年3月12日 星期日

如何擅用c# 的泛型 物件儲存oracle

當大家已經無法擺脫entityFramework的好處時,偏偏有些專案用一些特殊的資料庫或無法針對專案升級的老舊程式,此時只能自已下海寫傳統的SQL語法,但又不想每個欄位自已新增每個欄位的Parameter… 於是擅用c#的泛型就很重要囉! 因為只要擅用物件屬性,就讓它自已組SQL囉。

public bool OrcaleInsertData<T>(string tableName, T insertData) {
            OracleConnection oracleConn = (OracleConnection)Connection;
            try
            {
                if (oracleConn.State == ConnectionState.Closed)
                    oracleConn.Open();
                OracleCommand cmd = new OracleCommand();
                cmd.Connection = oracleConn;
                cmd.CommandType = CommandType.Text;
                StringBuilder strColumn = new StringBuilder();
                StringBuilder strSQLValue = new StringBuilder();
                Type type = typeof(T); //取得傳入物件的所有屬性
                List<OracleParameter> oracleParams = new List<OracleParameter>();
                //逐一的取物件的所有屬性值
foreach (PropertyInfo prop in type.GetProperties())
                {
                    object value = prop.GetValue(insertData);//逐一取得屬性值
                    if (value == null)
                        continue;
                    strColumn.Append(prop.Name + ","); //取得物件屬性名稱,視為資料庫的欄位名稱
                    strSQLValue.AppendFormat(":"+prop.Name + ",");//新增參數,ORACLE的參數為:
//如果物件的型態是允許NULL時,需要用以下的方式才能取得物件型態,否則只會囘傳nullable
                    var underlyingtype = Nullable.GetUnderlyingType(prop.PropertyType);
                    var reflactType = underlyingtype ?? prop.PropertyType;
                    OracleType columnType = getOrcaleType(reflactType.Name);//轉換型態                 
                    oracleParams.Add(new OracleParameter() {
                         ParameterName = prop.Name,
                         OracleType= columnType,
                         Value = prop.GetValue(insertData)//取得物件值
                    });
                }
                strColumn.Remove(strColumn.Length - 1, 1);
                strSQLValue.Remove(strSQLValue.Length - 1, 1);//remove the last,               
                cmd.Parameters.AddRange(oracleParams.ToArray());
                cmd.CommandText = string.Format("insert into {0} ( {1} ) values ({2})", tableName, strColumn.ToString(), strSQLValue.ToString());
                cmd.ExecuteNonQuery();
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
}

以下的範例只用來轉換型別,因為要針對Oracle的型別作轉換用途,目前只有簡單列出此專案所用到的欄位型態,如各位還有其他欄位型態,請自行增加囉~
     private OracleType getOrcaleType(string type) {
            switch (type.ToUpper()) {
                case "STRING":
                    return OracleType.Char;
                case "INT":
                    return OracleType.Int32;
                case "DECIMAL":
                    return OracleType.Double;
                case "DATETIME":
                    return OracleType.DateTime;
                case "BOOL":
                    return OracleType.Blob;
                default:
                    return OracleType.Char;
            }
        }



透過<T>就能傳入各種物件,再由Typeof(T)取得此物件的屬性和相對值,甚至屬性的型態都能清詳的列出,所以只需要把底層作好,以後不論任何物件都能呼叫此函式,多麼的方便~

 C# 本身也有推出OracleentityFramework的相關套件,但需要另外安裝…不過只支援到哪一版本entityFramework 本人就不清楚了,請各位自行研究囉!