動態Linq的邏輯與和邏輯或的條件查詢

最近在做一個數據檢索的工作,對一個數據庫中的寬表進行多個條件的檢索。爲了簡單方便快捷的完成這個功能,我使用LINQ to SQL+ReportView的方式來完成。

首先需要做的是一個查詢界面和寫一個數據庫查詢方法。用戶在輸入框中輸入多個指標,將根據指標的格式生成LINQ的Where語句。這個很容易實現,比如輸入“2003 北京 人口”,那麼就根據空格將這個字符串分成3個字符串,第一個字符串格式是年份,所以用表中的Year字段進行匹配,第二個字段是地區,所以再用表中的Location進行匹配,第三個是指標,那麼就用指標進行匹配,具體的C#代碼就是:

 public static List<Data2010> SearchData(string itemName)
        {
            using (DataClassesDataContext dc = new DataClassesDataContext())
            {
                var data = from d in dc.Data2010s
                           select d;
                string[] items = itemName.Split(' ');

                foreach (string item in items)
                {
                    if (IsYear(item))
                    {
                        int year = Convert.ToInt32(item);
                        data = data.Where(d => d.Year ==year);
                    }
                    else if (IsLocation(item))
                    {
                        string location=item;
                        data = data.Where(d => d.Location == location);
                    }
                    else
                    {
                        string keyword=item;
                        data = data.Where(d => d.Indicator.Contains(keyword));
                    }
                }

                return data.ToList();
            }
        }

這個功能還簡單,畢竟多個指標之間都是與的關係,但是接下來如果要實現或的關係,那麼又該怎麼辦呢?這個讓我傷了幾天的腦筋。比如說如果要搜索北京、上海、重慶的2000年和2010年的人口,那麼該怎麼查呢,我定義了一個簡單的語法,如果是或關係的指標,那麼就在小括號中用空格隔開。那麼查詢字符串就變成了:

(北京 上海 重慶)(2000 2010) 人口

這樣括號之間是與的關係,括號內的內容是或的關係。

但是真正的難點是如何用LINQ來實現動態的或查詢。我第一想到的是Dynamic LINQ(具體參見:這裏),這個在之前的項目中用過,特別強大,但是在這裏用起來不是很方便,所以又想自己實現一套動態OR查詢的方法,結果由於時間和能力有限,也沒有做出來,最後終於找到一個很好的類庫LinqKit,這個類庫中有一個

PredicateBuilder類,可以非常簡單的實現動態的邏輯或查詢。到網站中下載該類庫並添加到項目中,然後引用命名空間,將我們的搜索方法改爲如下內容:

public static List<Data2010> SearchData(string itemName)
{
    using (DataClassesDataContext dc = new DataClassesDataContext())
    {
        var data = from d in dc.Data2010s
                   select d;

        Regex r = new Regex(@"\([^\)]*\)");
        var ms = r.Matches(itemName);//匹配括號及其中的內容
        if (ms.Count > 0)
        {
            foreach (Match m in ms)
            {
                string name = m.Value.Substring(1, m.Value.Length - 2);//去掉括號,只剩下之間的內容
                string[] items = name.Split(' '); //各個Item之間是or的關係 空格區分

                var predicate = PredicateBuilder.False<Data2010>();
                foreach (string item in items)
                {
                    predicate = predicate.Or(WhereCondition(item));//這裏就是要用的動態邏輯或查詢

//WhereCondition的定義是:Expression<Func<Data2010, bool>> WhereCondition(string item),就是根據item的格式判斷該用哪個字段進行匹配


                }
                data = data.Where(predicate);//將最後的predicate傳入Where函數,相當於是對括號之間進行邏輯與查詢
            }
            itemName = r.Replace(itemName, " ");//把括號給替換掉,再對括號外的內容進行邏輯與查詢
        }

        string[] items2 = itemName.Split(' ');

        foreach (string item in items2)
        {
            data = data.Where(WhereCondition(item));
        }

        return data.ToList();
    }
}

數據庫查詢函數已經完成,接下來就是要用ReportViewer來展現查詢出來的結果綁定到報表中,具體代碼如下:

private void BindData(string q)
{
    var datas = DbOperation.SearchData(q);
    this.ReportViewer1.LocalReport.DataSources.Clear();
    this.ReportViewer1.LocalReport.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource(
                                                       "DataSet1", datas));
    this.ReportViewer1.DataBind();
}

這裏的DataSet1就是對於rdlc報表的數據源,不能寫錯。

發佈了224 篇原創文章 · 獲贊 5 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章