本系列目錄:
使用EF構建企業級應用(一):主要講數據庫訪問基類IRepository及Repository 的實現
使用EF構建企業級應用(二):主要講動態排序擴展的實現
使用EF構建企業級應用(三):主要講靈活的構建查詢條件表達式Expression<Func<TEntity,bool>>.
使用EF構建企業級應用(四):主要講下在MVC環境中前端開發中如何使用,及一個實例源碼包
在前面三篇文章中,我們大致的描述了使用EF如何方便的實現數據持久化,我們簡要的回憶下都有那些關鍵的內容段
- Repository基類的實現,
- 查詢條件Expression<Func<T,bool>>的構建
- 排序擴展
那么前端在使用MVC模式的時候,如何方便將我們前面所實現的銜接起來呢? 我們今天就來探討一下這個問題.
我們先來看看我們在實際項目中是如何使用的,如果你對這個寫法有興趣那再往下看(查詢界面我們采用JqGrid來展示數據)
/// <summary>
/// 查詢產品列表
/// </summary>
/// <returns></returns>
public ActionResult GetProductList()
{
string json = string.Empty;
if (WebRuntimes.LoginUser == null)
return Content(GetAlertMessageJson("會話已過期,請重新登錄"));
try
{
//構件查詢條件
var queryParam = GetQueryParam<Product, PgQueryProductExp>();int total = 0;
//查詢數據
var lst = SysServices.GetProductList(queryParam, out total);
//將lst轉化為jqgrid接受的json格式
json = JsonForJqgrid(lst, total, queryParam.PageSize, queryParam.PageIndex);
}
catch (Exception ex)
{
Logger.Log(ELogType.Error, ex);
json = GetAlertMessageJson("查詢失敗!");
}return Content(json);
}
也許你很快就發現了上述代碼中有兩個陌生的方法,構建查詢條件及從數據庫獲取數據,我們分別來看一下這兩個方法中都干了什么.
- 首先我們來看看在控制器基類中的構建查詢條件的這個方法定義:
/// <summary> /// 獲取頁面分頁查詢條件 /// </summary> /// <typeparam name="TEntity">待查詢的實體</typeparam> /// <typeparam name="TPgQueryExp">頁面查詢轉化類型</typeparam> /// <returns></returns> protected EFQueryParam<TEntity> GetQueryParam<TEntity, TPgQueryExp>() where TEntity : class where TPgQueryExp : class, IEFQueryExpression<TEntity>, new() { string sidx = "Code"; if (!string.IsNullOrEmpty(Request.QueryString["sidx"])) { sidx = Request.QueryString["sidx"].ToString(); } bool isSordAsc = false; if (!string.IsNullOrEmpty(Request.QueryString["sord"])) { if (Request.QueryString["sord"].ToString() == "asc") { isSordAsc = true; } } int pageSize = System.Convert.ToInt32(Request.QueryString["rows"]); int pageIndex = System.Convert.ToInt32(Request.QueryString["page"]) - 1; IEFQueryExpression<TEntity> exp = null; if (!string.IsNullOrEmpty(Request["d"])) { try { exp = GetObjectOfJson<TPgQueryExp>(Microsoft.JScript.GlobalObject.unescape(Request["d"])); } catch { } } if (exp == null) exp = new TPgQueryExp(); EFQueryParam<TEntity> ret = new EFQueryParam<TEntity>(exp, sidx, isSordAsc, pageIndex, pageSize); return ret; }
然后我們來看一下,代碼中有個陌生的對象PgQueryProductExp,那么他又做了什么呢?也許你已經猜到了,這個就是頁面查詢轉化條件的,來簡要的看一下是如何定義的
/// <summary>
/// 頁面查詢產品條件
/// </summary>
public class PgQueryProductExp : IEFQueryExpression<Product>
{
public string Code { get; set; }
public string Name { get; set; }
public string Specification { get; set; }
public Guid CategoryId { get; set; }
public int EnableFlag { get; set; }public PgQueryProductExp()
{
EnableFlag = 1;
}public Expression<Func<Product, bool>> GetExpression()
{var exp = EFExpression<Product>.CreateSignleLogic(ELogicType.And)
.Like(o => o.Code, Code)
.Like(o => o.Name, Name)
.Like(o => o.Specification, Specification);
if (CategoryId != Guid.Empty)
exp = exp.Equal(o => o.CategoryId, CategoryId);//條件中是否需要判斷是否有效?
if (EnableFlag > -1)
{
exp = exp.Equal(o => o.IsEnabled, (EnableFlag == 1));
}return exp.GetExpression();
}
其次我們來看一下在SysService 這個服務層中,我們是如何實現查詢的
/// <summary>
/// 查詢獲取產品數據
/// </summary>
/// <param name="queryParam">查詢參數</param>
/// <param name="total">返回符合條件的記錄總數</param>
/// <returns></returns>
public IList<Product> GetProductList(EFQueryParam<Product> queryParam, out int total)
{
total = 0;
IList<Product> lst = null;
using (var repository = new Repository<Product>())
{
lst = repository.Include(o => o.ProductCategory).Get(queryParam, out total).ToList();
}
if (lst != null)
lst = lst.Select(o => o.GetJsonEntity()).ToList();
return lst;
}
OK,這個就是一個完整的使用流程,貌似是很簡單的吧,不過細心的你也許已經發現了,我們在使用查詢的時候,貌似參查詢條件數並不是使用的在上一篇文章中的Expression<Func<T,bool>> 模式.而是使用這個EFQueryParam<T>類型.沒錯,我們在使用的時候,很多兄弟說,這個查詢方法的參數太多了,要求封裝一下,OK,那我們就來封裝一下吧
/// <summary> /// 封裝查詢參數 /// </summary> /// <typeparam name="TExpression">參數類型</typeparam> public abstract class QueryParam<TExpression> { /// <summary> /// 查詢條件 /// </summary> public TExpression Expression { get; set; } /// <summary> /// 排序字段 /// </summary> public string OrderPropertyName { get; set; } /// <summary> /// 是否是升序排序,為false時則對OrderPropertyName采取降序排序 /// </summary> public bool IsAscSort { get; set; } /// <summary> /// 分頁查詢,查詢第幾頁 /// </summary> public int PageIndex { get; set; } /// <summary> /// 分頁查詢,每頁顯示記錄數 /// </summary> public int PageSize { get; set; } /// <summary> /// 指示是否是分頁查詢 /// </summary> public bool IsPagingQuery { get { return PageSize > 0; } } } /// <summary> /// EF 實現的 QueryParam /// </summary> /// <typeparam name="TEntity">條件關聯實體類型</typeparam> public class EFQueryParam<TEntity> : QueryParam<Expression<Func<TEntity, bool>>> where TEntity : class { /// <summary> /// 實例化新的 EFQueryParam 實例 /// </summary> /// <param name="exp">查詢條件</param> /// <param name="orderPropertyName">排序屬性字段名</param> /// <param name="isAscSort">是否是升序排序,false為降序排序</param> /// <param name="pageIndex">分頁查詢,查詢第幾頁</param> /// <param name="pageSize">分頁查詢,每頁顯示記錄數</param> public EFQueryParam(Expression<Func<TEntity, bool>> exp, string orderPropertyName, bool isAscSort, int pageIndex, int pageSize) { this.Expression = exp; this.OrderPropertyName = orderPropertyName; this.IsAscSort = isAscSort; this.PageIndex = pageIndex; this.PageSize = pageSize; } /// <summary> /// 實例化新的 EFQueryParam 實例 /// </summary> /// <param name="exp">查詢條件</param> /// <param name="orderPropertyName">排序屬性字段名</param> /// <param name="isAscSort">是否是升序排序,false為降序排序</param> /// <param name="pageIndex">分頁查詢,查詢第幾頁</param> /// <param name="pageSize">分頁查詢,每頁顯示記錄數</param> public EFQueryParam(IEFQueryExpression<TEntity> exp, string orderPropertyName, bool isAscSort, int pageIndex, int pageSize) : this(exp.GetExpression(), orderPropertyName, isAscSort, pageIndex, pageSize) { }
OK,大功告成.本系列也就寫完了, 你可以通過這里下載完整的源碼包去自己嘗試.