ASP.NET MVC & EF 構建智能查詢 一、智能查詢的需求與設計

作者: 重典  來源: 博客園  發布時間: 2010-12-29 16:40  閱讀: 11420 次  推薦: 4   原文鏈接   [收藏]  

  關于復用

  在我們日常的開發過程中,代碼的復用其實是很重要的一部分,ASP.NET MVC框架本身為我們提供了很多很好的復用機制,讓我們能充分地利用它們來節省我們的Coding成本。

  在簡單的Coding中,我們可以通過構造方法來實現代碼段的復用,在OOP編程中我們可以使用繼承多態來進行類的復用,我們也可以使用設計模式來做類或對象間的代碼設計的復用,隨著程序的復雜我們就想構造出更佳的復用方式,可以向更高層次上抽象。

  應用場景與目標

  在信息管理系統中我們會開發大量的List頁面,它們功能上通常是非常相似的,一般是包含一個查詢條件組和一個列表。

  例如下圖所示:

image  那我的目標呢,就是對這里面的查詢功能進行封裝,以達到“只要更改頁面上的條件,就可以實現自動的查詢邏輯”這樣的功能,即:如果我們要加一個查詢條件則不需要修改邏輯代碼只修改頁面即可。

  其實對于一個有經驗的開發人員呢,根據HTML頁面的查詢條件去自動生成查詢結果并不是難事。最簡單的是將查詢提交表單遍歷,然后連接成一個SQL進行查詢。

  但是使用SQL有很多問題:

  1. 注入問題,因為不知道類型,所以很多地方都要拼寫引號就算是使用Parameter,也無法處理類型轉換的問題
  2. 無法處理Or和And共存的問題
  3. 無法處理其它查詢條件如大于小于Like

  那我們想一下我們使用EF的話是如何正常去編寫一個查詢的呢,我們通常是在邏輯中去拼SQL或是寫如下的EF:

 
var query = db.User.AsQueryable();
if (string.IsNullOrEmpty(name))
query
= query.Where(c => c.Name == name);
if (id.HasValue)
query
= query.Where(c => c.Id == id);
if (string.IsNullOrEmpty(email))
query
= query.Where(c => c.Email == email);
return query.ToList();

  那我們的目標其實就明確了,我們就是要讓代碼自動去完成上述這一過程,并且可以支持:

  1. 識別類型(EF的話這個很重要)
  2. 僅查詢有效條件
  3. 處理可空類型
  4. 處理類型轉換(如DateTime與UnixTime的轉換)
  5. 一些代碼性邏輯(比如查詢某些日期的時候,其實我們要的結果并不是c=>c.Time==time而是c=>c.Time>time && c.Time<time.AddDays(1))
  6. 支持Or等 混合查詢
  7. 關于Like的相關處理
  8. 關于In操作的相關處理
  9. Join查詢的相關處理

  理論流程

  看一看我們要做的其實還挺多的,但是我已經在心里搭出了一個這樣的流程,使用ASP.NET MVC及EF特性來完成這些功能

image  那其實呢首先的問題就是我們從瀏覽器請求向服務器的時候,除了要查詢的字段,還應該包含有 怎么查(就是操作符,比如= < > like in)、是否為Or、而HTML中唯一可以直接傳到服務器的就是表單元素的name所以我們可以對name來做一些手腳讓它包含這些信息,比如[Equal]Id就表示讓Id這個屬性的值等于這個表單項的Value。

 
[Equal]Id=1

  我們就利用這個postdata或QueryString去構造出c=>c.Id==1的Lambda表達式,并且支持多個條件。

  實際實現

  而我是在Helper上加了一層擴展來實現這樣的功能的,形如:

 
<form action="" method="post">
姓名:@Html.TextBox("Name").ForSearch(QueryMethod.Like)
Email:@Html.TextBox("Email").ForSearch(QueryMethod.Equal)
<br />
Id: @Html.TextBox("Id").ForSearch(QueryMethod.Equal)
生日: @Html.TextBox("Birthday").ForSearch(QueryMethod.Equal)
<br />
<input type="submit" value="查詢" />
</form>

  這里我們使用ForSearch這個擴展為Html的name添加了前置的謂詞標記[Equal],我們在服務器端只要統一處理:

 
public ActionResult Index(QueryModel model)
{

using(var db=new DbEntities())
{
var list
= db.Users.Where(model).ToList();
return View(list);
}
}

  我們是在這個Where的擴展方法里重寫了將QueryModel轉換成lambda表達式的工作,當然在這之前我們還利用了自已實現的ModelBinder去將 postdata/querystring進行了分析前初始化了QueryModel。

  在未來的幾篇中我們將會詳述這些過程的實現:ASP.NET MVC & EF 構建智能查詢 二、模型的設計與ModelBinder

4
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()