001 SqlSugar 查詢擴展

001 SqlSugar 查詢擴展


博客園Id:13041713


提出問題

有的時候我們在進行單表查詢時,可能需要的條件有很多,但是,我們需要一一來判斷,查詢參數是否爲空,如果爲空就不使用這個字段來作爲查詢條件,在這種情況下,我們會寫大量的if語句,這是一種重複的工作,我們應該如何避免這樣的問題呢?

下面是重複代碼的示例程序代碼:

/// <summary>
/// 加載登錄信息
/// </summary>
/// <returns></returns>
public IActionResult LoadAllLoginInfo(LoginInfoReqDto loginInfoReqDto)
{

    var totalCount = 0;

    var querySqlQueryable = this._context.Queryable<sys_loginfo>();


    if (!string.IsNullOrEmpty(loginInfoReqDto.LoginName))
    {
        querySqlQueryable = querySqlQueryable.Where(x => x.loginname == loginInfoReqDto.LoginName);
    }

    if (!string.IsNullOrEmpty(loginInfoReqDto.LoginIp))
    {
        querySqlQueryable = querySqlQueryable.Where(x => x.loginip == loginInfoReqDto.LoginIp);
    }
   

    if (loginInfoReqDto.StartTime != DateTime.MinValue)
    {
        querySqlQueryable = querySqlQueryable.Where(x => x.logintime >= loginInfoReqDto.StartTime);
    }

    if (loginInfoReqDto.EndTime != DateTime.MinValue)
    {
        querySqlQueryable = querySqlQueryable.Where(x => x.logintime <= loginInfoReqDto.EndTime);
    }

    var queryResult = querySqlQueryable.OrderBy(x => x.id, OrderByType.Desc)
        .ToPageList(loginInfoReqDto.Page, loginInfoReqDto.Limit, ref totalCount);

    var result = new LoginInfoResDto
    {
        Code = 0,
        Msg = "查詢成功",
        Count = totalCount,
        Data = queryResult
    };

    return Json(result);
}#

上面代碼中,我們可以看到有很多拼裝表達式樹的過程代碼. 這樣的話,往往需要我們寫很多無意義的冗餘代碼.

下面我們把代碼精簡一下.

簡化代碼如下:

/// <summary>
/// 加載登錄信息
/// </summary>
/// <returns></returns>
public IActionResult LoadAllLoginInfo(LoginInfoReqDto loginInfoReqDto)
{

    var totalCount = 0;

    var querySqlQueryable = this._context.Queryable<sys_loginfo>();
    querySqlQueryable = this._context.Queryable<sys_loginfo>().Where(loginInfoReqDto);
	
    var queryResult = querySqlQueryable.OrderBy(x => x.id, OrderByType.Desc)
        .ToPageList(loginInfoReqDto.Page, loginInfoReqDto.Limit, ref totalCount);

    var result = new LoginInfoResDto
    {
        Code = 0,
        Msg = "查詢成功",
        Count = totalCount,
        Data = queryResult
    };

    return Json(result);
}

通過上面的代碼,我們簡化了很多不需要的if語句拼裝表達式樹的過程.

核心SqlSugar查詢擴展代碼如下:

using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace SqlSugar
{
    public static class SqlSugarExt
    {
        /// <summary>
        /// 根據條件對象查詢數據
        /// </summary>
        /// <typeparam name="T">表實體對象</typeparam>
        /// <param name="sugarQueryable">sugar查詢對象</param>
        /// <param name="whereObj">查詢實體</param>
        /// <returns></returns>
        public static ISugarQueryable<T> Where<T>(this ISugarQueryable<T> sugarQueryable, object whereObj)
        {
            var sugarQueryableWhere = sugarQueryable;

            var whereObjType = whereObj.GetType();
            var whereDic = new Dictionary<string, object>();      //裝載where條件
            var inDic = new Dictionary<string,List<int>>();       //裝載in條件

            foreach (var property in whereObjType.GetProperties())
            {
                var curName = property.Name;
                if (property.PropertyType.Name.Equals("List`1"))  //集合
                {
                    var curValue = property.GetValue(whereObj, null);
                    inDic.Add(curName, (List<int>)curValue);
                }
                else
                {
                    var curValue = property.GetValue(whereObj, null);
                    if (curValue==null) continue;                //排除參數值爲null的查詢條件
                    whereDic.Add(curName.ToLower(), curValue);
                }
            }

            var dbModelType = typeof(T);

            var expSb = new StringBuilder();

            foreach (var property in dbModelType.GetProperties())      //遍歷dbModel屬性
            {
                foreach (var (key, value) in whereDic)                     
                {
                    if (property.Name.ToLower() != key) continue;

                    expSb.Append(ProcessExp(property,value));          //拼接where條件
                    expSb.Append(" and ");
                }
            }

            if (expSb.Length != 0)                                     //轉換where條件表達式樹
            {
                var exp = expSb.ToString().Remove(expSb.Length - 4, 4);

                var e = System.Linq.DynamicCore.DynamicExpression.ParseLambda<T, bool>(exp);

                sugarQueryableWhere = sugarQueryable.Where(e);
            }


            if (inDic.Count == 0) return sugarQueryableWhere;

            foreach (var (key, value) in inDic)                       //轉換in條件表達式樹
            {
                var e2 = System.Linq.DynamicCore.DynamicExpression.ParseLambda<T, object>(key);
                sugarQueryableWhere = sugarQueryableWhere.In(e2, value);
            }

            return sugarQueryableWhere;
        }

        /// <summary>
        /// 處理表達式樹拼接
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string ProcessExp(PropertyInfo property,object value)
        {
           
            //引用類型 此處只考慮string類型的情況
            if (!property.PropertyType.IsValueType) return $"{property.Name} = \"{value}\" ";

            //可空值類型 此處只考慮簡單值類型
            if (property.PropertyType.Name.Equals("Nullable`1"))   
            {
                if (property.PropertyType.GenericTypeArguments[0].Name.Equals("DateTime"))
                {
                    return $"{property.Name} = Convert.ToDateTime(\"{value}\") ";
                }
                    
                return $"{property.Name} = {value} ";
            }

            //值類型  此處只考慮簡單值類型
            if (property.PropertyType.Name.Equals("DateTime"))  
            {
                return $"{property.Name} = Convert.ToDateTime(\"{value}\") ";
            }

            return $"{property.Name} = {value} ";

            
        }

       
        
    }
}

以上代碼需要在項目中,引入如下程序集:
動態Linq生成

開源代碼下載地址 請根據使用的項目,自行選擇編譯指定項目,後獲取dll,導入到自己的項目中.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章