背景
Orm用過一些,但處理增删改上面做的都不錯。但是查詢上跟我想要的效果總是差了一點。我想要的效果則是這樣,基于某種命名規則進行傳參,背景解析器知道命名規則即可知道它要查詢什麼樣的資料。
談談我之前的做法,比如說,頁面将查詢條件存入對象,序列化後後傳遞給控制器,此時控制器将其反序列化成Json,資料類型使用Dictionary<string,object>。裡面存儲的Key目前是這樣的格式: BeginTime, EndTime, Age, LikeAddress , NullTel , UnLikeMM , 其中 Begin End Like UnLike Null 等是自定義的命名規則,告訴背景我需要查詢的資料類型,具體的含義看字首大緻即可知道。如傳入BeginTime=2013-10-31 21:55:47,希望得到時間大于這個值的數。
當時背景則是嘗試去判斷每一個值,如使用 Dictionary.TryGetValue("BeginTime",out obj) , 來進行條件的傳值判斷。這個地方還存在一個類型問題,時間到了背景變成了時間字元串,而不是DateTime類型。此處則需要強制轉換。也正式因為這些原因,代碼寫的不大工整,盡管做了一些封裝,稍微簡潔點,但還不是我要的效果。
以此為主題,寫了一個初步的實作,希望各位朋友能給出部分建議,如果有類似的成熟的架構,能讓我在背景定義個SQL之後,前端隻要傳入規定的命名字段,即可完成查詢,這樣是再好不過了。
測試效果
var strSql = "select * from Users where ";
var dic = new Dictionary<string, object>();
dic["BeginAge"] = "18";//Age>=18
dic["EndAge"] = 80;//Age<=80
dic["LikeName"] = "玲";//Name包含'玲'
dic["IsGirl"] = "true";//IsGirl = true
dic["BeginLoginTime"] = DateTime.Now.AddDays(-7);//LoginTime >= 七天前
dic["EndLoginTime"] = DateTime.Now.ToString();//LoginTime <= 今天
//部分類型若不正确,則需要手動映射
SqlMapper mapper = new SqlMapper(dic);
mapper.LoadTypeMapper<DateTime>("LoginTime");
mapper.LoadTypeMapper<int>("Age");
mapper.LoadTypeMapper<bool>("IsGirl");
//看看生成的條件語句
var where = mapper.Where();
Console.WriteLine("{0} {1}", strSql, where);
Console.WriteLine();
目前的效果則如圖,得到對應的SQL語句,并且将資料類型轉換正确。
我們在看看複雜的查詢。
strSql = "select * from Table1 t1 inner join Table2 t2 on t1.ID=t2.Table1ID where ";
dic["t1.UserName"] = "admin";//UserName='admin'
dic["t1.BeginAge"] = 18;//Age>=18
dic["t1.EndAge"] = "80";//Age<=80
dic["t1.NullSex"] = "false";//Sex is not null
dic["t1.NullNice"] = "true";//Nice is true
dic["t2.LikeHomeName"] = "中國";//HomeName like '%中國%'
dic["t2.UnLikeAddress"] = "郊區";//Address not like '%郊區%'
dic["t2.BeginCreateTime"] = DateTime.Now.ToString();//CreateTime >= DateTime.Now
mapper = new SqlMapper(dic);
mapper.LoadTypeMapper<DateTime>("CreateTime");
mapper.LoadTypeMapper<int>("Age");
mapper.LoadTypeMapper<bool>("Sex");
where = mapper.Where();
Console.WriteLine("{0} {1}", strSql, where);
Console.WriteLine();
//看看格式化後的Dictionary
foreach (var e in dic)
{
Console.WriteLine("{0}:{1} {2}", e.Key, e.Value, e.Value.GetType());
}
我想要的效果,大緻就是這樣,由于是測試代碼,是以直接構造了Dictionary,并且寫入了對應的資料(類型有正确有錯誤)。
實作方式很簡單,則是周遊Dictionary,根據命名規則定義的字首,來拼接SQL語句,并且檢測目前類型,如果是string類型,則需要和映射的類型比對一下,不相同,則将string類型轉換成Mapper中映射的類型。
最後在重申一下我想達到的目的,背景定義SQL語句,如Select ....,方法接收Dictionary參數,解析後傳遞給ado或者orm去執行,如此一來,前端想查詢什麼樣的資料,隻需要定義條件就好了。
測試代碼下載下傳