问题以及想要的效果,不重复叙述,如果需要的请先看 理想中的SQL语句条件拼接方式 。
现在有2个类映射数据库的2张表,结构如下:
public class User { public int UserID { get; set; } public string Name { get; set; } public int Age { get; set; } public bool IsGirl { get; set; } public DateTime LoginTime { get; set; } } public class Log { public int UserID { get; set; } public string Content { get; set; } public int LogID { get; set; } public DateTime CreateTime { get; set; } public bool IsCreasy { get; set; } }
首先我们可能需要查询用户信息(单表查询),条件不定。来看看我们要写的代码:
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(); mapper.SelectSingle<User>(dic, "t1");
我们可以由此得到拼接后的SQL语句,看看通过Mapper得到的SQL语句是什么样子。
t1.Age >= @BeginAge AND t1.Age <= @EndAge AND t1.Name like '%'+@Name+'%' AND t1.IsGirl = @IsGirl AND t1.LoginTime >= @BeginLoginTime AND t1.LoginTime <= @EndLoginTime
然后参数存储在Dictionary<string,object>对象中,参数则是经过通过User类型映射后的。
对于单表查询,可以直接在C#代码中这样写查询条件,也可以是由页面构造的Json传递后台,通过反序列化得到的Dictionary<string,object>对象。
下面我们来看看联合查询下条件怎么写。假定SQL语句是这样:
select * from User t1 inner join Log t2 on t1.UserID=t2.UserID where
最终我是希望通过Js直接将参数传递给后台,构造条件与参数,然后将条件与该SQL语句进行拼接,交给ado或者orm去执行。由于是联表查询,可能需要通过映射多个类型,所以我使用了如下数据结构:Dictionary<string,Dictionary<string,object>> , 意思则是实体与实体条件的一个字典集合。
首先在C#端构造该数据结构及调用方式。
dicMulty["t1"] = new Dictionary<string, object>(); dicMulty["t1"]["UserID"] = "1"; dicMulty["t1"]["Name"] = "xxx"; dicMulty["t1"]["BeginAge"] = "18";//Age>=18 dicMulty["t1"]["EndAge"] = 80;//Age<=80 dicMulty["t1"]["LikeName"] = "玲";//Name包含'玲' dicMulty["t1"]["IsGirl"] = "true";//IsGirl = true dicMulty["t1"]["BeginLoginTime"] = DateTime.Now.AddDays(-7);//LoginTime >= 七天前 dicMulty["t1"]["EndLoginTime"] = DateTime.Now.ToString();//LoginTime <= 今天 dicMulty["t2"] = new Dictionary<string, object>(); dicMulty["t2"]["LogID"] = "1"; dicMulty["t2"]["UserID"] = "1"; dicMulty["t2"]["LikeContent"] = "坏事";//Age>=18 dicMulty["t2"]["IsCreasy"] = "false";//Age<=80 dicMulty["t2"]["CreateTime"] = "2013-11-05 10:52:37";// mapper.SelectMulity<User, Log>(dicMulty, "t1", "t2");
看看生成的SQL语句,其中条件中故意在t1表,和t2表,均使用了UserID查询。
t1.UserID = @UserID AND t1.Name = @Name AND t1.Age >= @BeginAge AND t1.Age <= @EndAge AND t1.Name like '%'+@Name+'%' AND t1.IsGirl = @IsGirl AND t1.LoginTime >= @BeginLoginTime AND t1.LoginTime <= @EndLoginTime AND t2.LogID = @LogID AND t2.UserID = @UserID1 AND t2.Content like '%'+@Content+'%' AND t2.IsCreasy = @IsCreasy AND t2.CreateTime = @CreateTime
但是在目前的场景中,经常是由Js将条件传递过来,我们看看Js端是怎么调用的呢。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script src="jquery-1.7.1.min.js"></script> <%--<script src="jquery.json-2.4.min.js"></script>--%> </head> <script> function test() { var a = { t1: {}, t2: {} }; a.t1.UserID = "1"; a.t1.Name = "xxx"; a.t1.BeginAge = "18"; a.t1.EndAge = 80; a.t1.LikeName = "玲"; a.t1.IsGirl = "true"; a.t1.BeginLoginTime = "2013-10-01 11:22:13";// a.t1.EndLoginTime = "2013-11-05 11:22:23";// a.t2.LogID = "1"; a.t2.UserID = "1"; a.t2.LikeContent = "坏事"; a.t2.IsCreasy = false; a.t2.CreateTime = new Date(); var json = JSON.stringify(a); $.post("Handler1.ashx", { "para": json }, function (data) { alert(data); }, 'json'); } </script> <body> <form id="form1" runat="server"> <div> <input type="button" value="测试" onclick="test()" /> </div> </form> </body> </html>
目前可能在单表、或者联合查询上,满足了我的需求。
最后我想,如果在实际应用中,可能我想直接在后台写条件,根本就不需要做什么类型映射,按照命名规则条件,直接把条件拼接出来就好了。在单表查询上都好说,像前面介绍的方式来写,倒也不麻烦,可联合查询,如果像前面写的,那样太麻烦了,还不如直接拼接SQL去,所以想了想,整成如下模样:
dic["t1.UserID"] = 1; dic["t1.Name"] = "xxx"; dic["t1.BeginAge"] = 18;//Age>=18 dic["t1.EndAge"] = 80;//Age<=80 dic["t1.LikeName"] = "玲";//Name包含'玲' dic["t1.IsGirl"] = true;//IsGirl = true dic["t1.BeginLoginTime"] = DateTime.Now.AddDays(-7);//LoginTime >= 七天前 dic["t1.EndLoginTime"] = DateTime.Now.ToString();//LoginTime <= 今天 dic["t2.LogID"] = 1; dic["t2.UserID"] = 1; dic["t2.LikeContent"] = "坏事";//Age>=18 dic["t2.IsCreasy"] = false;//Age<=80 dic["t2.CreateTime"] = DateTime.Parse("2013-11-05 10:52:37"); mapper.Select(dic);
拼接得到的SQL和之前是一样,这里就不反复贴了。
大伙看看这样是否可行呢。
测试代码下载