理想中的SQL語句條件拼接方式


背景

  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去執行,如此一來,前端想查詢什么樣的數據,只需要定義條件就好了。

 

  測試代碼下載

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM