前言
搜索功能是一個很常用的功能,當然這個搜索不是指全文檢索,是指網站的后臺管理系統或ERP系統列表的搜索功能。常見做法一般就是在搜索欄上加上幾個常用字段來搜索。代碼可能一般這樣實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
StringBuilder sqlStr = new StringBuilder(); if (! string .IsNullOrEmpty(RealName)) { sqlStr.Append( " and RealName = @RealName" ); } if (Age != -1) { sqlStr.Append( " and Age = @Age" ); } if (! string .IsNullOrEmpty(StartTime)) { sqlStr.Append( " and CreateTime >= @StartTime" ); } if (! string .IsNullOrEmpty(EndTime)) { sqlStr.Append( " and CreateTime <= @EndTime" ); } MySqlParameter[] paras = new MySqlParameter[]{ new MySqlParameter( "@Age" , Age), new MySqlParameter( "@RealName" , RealName), new MySqlParameter( "@StartTime" , StartTime), new MySqlParameter( "@EndTime" , EndTime) }; |
這段代碼如果遇到下面幾個需求,又該如何處理?
- 再加一個查詢字段
- RealName需要改成模糊查詢
- Age需要支持范圍查詢
可能大多數程序猿想法,這是新的需求,那么就直接改代碼,簡單粗暴。然后在前臺加個age范圍文本框,后臺再加個if判斷,realname的=號就直接改成like,就這樣輕松搞定了。但需求總是不斷變化,如果一張表有50個字段,同時需要支持其中40個字段查詢。我想大都數人第一反應:臥槽,神經病!難道就沒有一個通用的辦法來解決這種搜索的問題?我想說當然有,本文接下來就用DapperExtensions和反射的來解決這個問題,最終于實現的效果如下圖:
DapperExtensions介紹
DapperExtensions是基于Dapper的一個擴展,主要在Dapper基礎上實現了CRUD的操作。它還提供了一個謂詞系統,可以實現更多復雜的高級查詢功能。還可以通過ClassMapper來定義實體類和表的映射。
通用搜索功能實現
1.首先創建一個account表,然后增加一個Account類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public class Account { public Account() { Age = -1; } /// <summary> /// 賬戶ID /// </summary> [Mark( "賬戶ID" )] public int AccountId { get ; set ; } /// <summary> /// 姓名 /// </summary> [Mark( "姓名" )] public string RealName { get ; set ; } /// <summary> /// 年齡 /// </summary> [Mark( "年齡" )] public int Age { get ; set ; } /// <summary> /// 創建時間 /// </summary> [Mark( "創建時間" )] public DateTime CreateTime { get ; set ; } } |
2.為了獲取字段對應的中文名稱,我們增加一個MarkAttribute類。因為有強大的反射功能,我們可以通過反射動態獲取每張表實體類的屬性和中文名稱。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
[AttributeUsage(AttributeTargets.Property, Inherited = false , AllowMultiple = true )] public class MarkAttribute : Attribute { public MarkAttribute( string FiledName, string Description = "" ) { this .FiledName = FiledName; this .Description = Description; } private string _FiledName; public string FiledName { get { return _FiledName; } set { _FiledName = value; } } private string _Description; public string Description { get { return _Description; } set { _Description = value; } } } |
3.通用搜索思路主要是把搜索功能抽象出一個對象,本質上也就列名、操作符、值組成的一個對象集合,這樣就可以實現多個搜索條件的組合。我們增加一個Predicate類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class Predicate { /// <summary> /// 列名 /// </summary> public string ColumnItem { get ; set ; } /// <summary> /// 操作符 /// </summary> public string OperatorItem { get ; set ; } /// <summary> /// 值 /// </summary> public object Value { get ; set ; } } |
4.然后通過反射Account類的屬性加載到前臺列名的DropDownList,再增加一個操作符的DropDownList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
var columnItems = new List<SelectListItem>(); //通過反射來獲取類的屬性 Type t = Assembly.Load( "SearchDemo" ).GetType( "SearchDemo.Models.Account" ); foreach (PropertyInfo item in t.GetProperties()) { string filedName = (item.GetCustomAttributes( typeof (MarkAttribute), false )[0] as MarkAttribute).FiledName; columnItems.Add( new SelectListItem() { Text = filedName, Value = item.Name }); } ViewBag.columnItems = columnItems; var operatorItems = new List<SelectListItem>() { new SelectListItem() {Text = "等于" , Value = "Eq" }, new SelectListItem() {Text = "大于" , Value = "Gt" }, new SelectListItem() {Text = "大于或等于" , Value = "Ge" }, new SelectListItem() {Text = "小于" , Value = "Lt" }, new SelectListItem() {Text = "小于或等于" , Value = "Le" }, new SelectListItem() {Text = "模糊" , Value = "Like" } }; ViewBag.operatorItems = operatorItems; |
5.前臺界面實現代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
<!DOCTYPE html> <html> <head> <title>DapperExtensions通用搜索</title> <script src= "../../Scripts/jquery-1.4.4.min.js" type= "text/javascript" ></script> <script type= "text/javascript" > Date.prototype.format = function (format) { var o = { "M+" : this .getMonth() + 1, //month "d+" : this .getDate(), //day "h+" : this .getHours(), //hour "m+" : this .getMinutes(), //minute "s+" : this .getSeconds(), //second "q+" : Math.floor(( this .getMonth() + 3) / 3), //quarter "S" : this .getMilliseconds() //millisecond } if (/(y+)/.test(format)) { format = format.replace(RegExp.$1, ( this .getFullYear() + "" ).substr(4 - RegExp.$1.length)); } for (var k in o) { if ( new RegExp( "(" + k + ")" ).test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ( "00" + o[k]).substr(( "" + o[k]).length)); } } return format; } </script> <style type= "text/css" > ul { list-style: none; padding: 0px; margin: 0px; width: 590px; height: 20px; line-height: 20px; border: 1px solid #99CC00; border-top: 0px; font-size: 12px; } ul li { display: block; width: 25%; float : left; text-indent: 2em; } .th { background: #F1FADE; font-weight: bold; border-top: 1px solid #99CC00; } </style> <script type= "text/javascript" > var predicates = []; var index = 0; $(document).ready(function () { $( "#btnAdd" ).click(function () { var columnItem = $( "#columnItems option:selected" ); var operatorItem = $( "#operatorItems option:selected" ); var value = $( "#value" ).val(); if (value == "" ){ alert( "請輸入值" ); return ; } var predicate = { index: index, columnItem: columnItem.val(), operatorItem: operatorItem.val(), value: value }; predicates.push(predicate); var html = "<ul><li>" + columnItem.text() + "</li><li>" + operatorItem.text() + "</li><li>" + value + "</li><li><a href='javascript:;' onclick='del(this," + index + ")'>刪除</a></li></ul>" $( "#predicates ul:last" ).after(html); index++; }) $( "#btnSearch" ).click(function () { $.ajax({ type: "POST" , url: "home/search" , data: JSON.stringify(predicates), contentType: "application/json" , success: function (data) { if (data.Error != null ) { alert(data.Error); return ; } $( "#list .th" ).nextAll().remove(); var html = "" ; $.each(data, function (index, item) { html += "<ul><li>" + item.AccountId + "</li>" ; html += "<li>" + item.RealName + "</li>" ; html += "<li>" + item.Age + "</li>" ; //轉換日期 var dateMilliseconds = parseInt(item.CreateTime.replace(/\D/igm, "" )); var date = new Date(dateMilliseconds); html += "<li>" + date.format( "yyyy-MM-dd hh:mm:ss" ) + "</li></ul>" ; }); $( "#list .th" ).after(html); } }); }) }) function del(obj,index) { obj.parentNode.parentNode.remove(); for (var i = 0; i < predicates.length; i++) { if (predicates[i].index == index) { predicates.splice(i, 1); } } } </script> </head> <body> <div> 列名:@Html.DropDownList( "columnItems" ) 操作符:@Html.DropDownList( "operatorItems" ) 值:@Html.TextBox( "value" ) <input id= "btnAdd" type= "button" value= "增加" /> <input id= "btnSearch" type= "button" value= "搜索" /> </div> <br /> <div id= "predicates" > <ul class = "th" > <li>列名</li> <li>操作符</li> <li>值</li> <li>操作</li> </ul> </div> <br /> <div id= "list" > <ul class = "th" > <li>賬戶ID</li> <li>姓名</li> <li>年齡</li> <li>創建時間</li> </ul> </div> </body> </html> |
6.最后通過DapperExtensions的謂詞和反射實現搜索方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[HttpPost] public JsonResult Search(List<Predicate> predicates) { if (predicates == null ) { return Json( new { Error = "請增加搜索條件" }); } using (var connection = SqlHelper.GetConnection()) { var pga = new PredicateGroup { Operator = GroupOperator.And, Predicates = new List<IPredicate>() }; foreach (var p in predicates) { var predicate = Predicates.Field<Account>(GetExpression(p), (Operator)Enum.Parse( typeof (Operator), p.OperatorItem), p.Value); pga.Predicates.Add(predicate); } var list = connection.GetList<Account>(pga); return Json(list); } } private static Expression<Func<Account, object >> GetExpression(Predicate p) { ParameterExpression parameter = Expression.Parameter( typeof (Account), "p" ); return Expression.Lambda<Func<Account, object >>(Expression.Convert(Expression.Property(parameter, p.ColumnItem), typeof ( object )), parameter); } |
最終,通過簡單的幾行代碼,在基于DapperExtensions的功能基礎上,我們最終實現了一個可以支持多個字段、多個條件、多個操作符的通用查詢功能。本文也只是拋磚引玉,只是提供一種思路,還有更多細節沒有考慮。比如多個條件的組合可以再增加一個邏輯符來連接、多個條件組合嵌套查詢、多表查詢等等。
以上所述是小編給大家介紹的Asp.net中使用DapperExtensions和反射來實現一個通用搜索,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/yt1983/p/6485499.html