摘要:[ASP.NET] DataReader自動mapping到object
最近有點時間,整理紀錄一下平常用的一些小程式
因為蠻懶的所以如果在效能上不是很要求的物件,總是會用上一些小程式來處理,
像蠻喜歡把從DB叫出來的DataReader,用Reflection寫入物件中,
但有幾個前提要注意,
(1) 物件的property 的命名要和DataReader的Column Name 一樣,如果不一樣就只好自己做一個dictionary去mapping
(2) 物件的property請使用public,因為用private的話無法reflect 出來,也無法塞值進去
這是一個很簡單的例子,如果有錯請多包涵
先做一個簡單的Enity
public class IBECommonEntity
{
public int Idnum { get; set; }
public EnableEnum Enable { get; set; }
public StatusEnum Status { get; set; }
public string Creater { get; set; }
public DateTime CreateDate { get; set; }
public string Modifier { get; set; }
public DateTime? ModifyDate { get; set; }
}
public class BEStatus : IBECommonEntity
{
public BEStatus(){}
public string Name { get; set; }
public string Test { get; set; }
public StatusDataEnum StatusCategory { get; set; }
}
然後我的Table結構如下
準備個簡單的Stored Procedure
CREATE PROCEDURE [dbo].[HR_GetStatusData_001]
@StatusCategory int = NULL
AS
BEGIN
SELECT * from [StatusData] with(nolock) where
(@StatusCategory is NULL or StatusCategory = @StatusCategory)
and ([Status] = 0)
END
寫一個簡單的物件來呼叫DB
public class DBSetting
{
//DBSource是一個自訂的Enum,主要是要讓我寫的其他程式取得我的DB Connection String(我只要點一下後面的字就出來了,原因還是懶)
public static IDataReader GetDataReader(DBSource dbconstrID, string spID)
{
//這邊是我取得Connection String,程式就不寫了
string cnstr = GetDBConnection(dbconstrID) ?? string.Empty;
//這邊是我用Key值去取得我的SP Name
string sp = GetSPValue(spID) ?? string.Empty;
if (!string.IsNullOrEmpty(cnstr) && !string.IsNullOrEmpty(sp))
{
//簡單的寫一個取得DataReader方式,不傳Parameter了,相信很多人都非常厲害
SqlConnection cn = new SqlConnection(cnstr);
SqlCommand cmd = new SqlCommand(sp, cn);
cmd.CommandType = CommandType.StoredProcedure;
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
return dr;
}
return null;
}
}
做一個Helper來處理把Dataredaer自動放入Object
public class DBHelper
{
//用一個簡單的Reflection去把資料放入
public static object DataReaderMapping(IDataReader dr, object obj)
{
PropertyInfo[] ps = obj.GetType().GetProperties();
foreach (PropertyInfo p in ps)
{
p.SetValue(obj, ReturnValue(dr[p.Name]), null);
}
return obj;
}
//寫一個簡單的方式來過濾DataReader的資料
private static object ReturnValue(object data)
{
string typename = data.GetType().Name.ToLower();
if (typename.Contains("string"))
{
return data.ToString();
}
if (typename.Contains("int"))
{
return int.Parse(data.ToString());
}
if (typename.Contains("datetime"))
{
DateTime dateTimeValue = new DateTime();
DateTime.TryParse(data.ToString(), out dateTimeValue);
return dateTimeValue;
}
if (typename.Contains("decimal"))
{
return decimal.Parse(data.ToString());
}
return null;
}
}
最後做一個Object來處理我的Enity,以後就可以不斷的呼叫Helper來幫忙
public class BOStatus
{
public static IList getData()
{
List statusList = new List();
IDataReader dr = DBSetting.GetDataReader(DBSource.MainDBConstr, "GetStatusData");
while (dr.Read())
{
List drlist = new List();
if (drlist.Count <= 0)
{
drlist = DBHelper.DataReaderNameList(dr);
}
statusList.Add((BEStatus)DBHelper.DataReaderFilterMapping(dr, new BEStatus(), drlist));
}
return statusList;
}
}
以上我們就可以很輕易的把DataReader放入我們的物件,不用再人工的一筆一筆寫,
最後一步,就是簡單的把它呈現在頁面
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "this is a test";
IList list = BOStatus.getData();
ViewBag.CountNum = list.Count;
return View();
}
}
明眼人一看就知道我用MVC的範例,而且連改都懶得改 (慚愧)
以為這樣就結束了嗎? 當然還是有些問題,比較大的問題像是當我物件有增加新的property時,但DataReader沒有怎辦?
很簡單,系統就會拋異常,也就是給你錯誤畫面了,所以可以在DBHelper裡面做一個過濾去處理,這樣很簡單就處理掉了
END...