2012-03-21 84 views
1

我正在爲一組文件的結果進行小型查詢。組合LINQ查詢

public class f_results 
    { 
     public String name { get; set; } 
     public DateTime cdate { get; set; } 
     public DateTime mdate { get; set; } 
     public DateTime adate { get; set; } 
     public Int64 size { get; set; } 
    } 

我有一個用戶可以選擇他們想要的屏幕。目前,我經過一個過濾系統:

foundfiles = new BindingList<f_results>(totalresults.Find(fname.Text,true)); 
    if (fsize.Text.Trim() != "") 
    { 
     try 
     { 
      Int64 sz = Int64.Parse(fsize.Text); 
      List<f_results> y = (from p in foundfiles where p.size >= sz orderby p.size descending select p ).ToList(); 
      foundfiles = new BindingList<f_results>(y); 
     } 
     catch 
     { } 
    } 
    if (adate.Text.Trim() != "") 
    { 
     try 
     { 
      List<f_results> y; 
      DateTime test = DateTime.Parse(adate.Text); 
      if ((adateop.Text) == ">") 
      { 
       y = (from p in foundfiles where p.adate >= test select p).ToList(); 
      } 
      else 
       y = (from p in foundfiles where p.adate <= test select p).ToList(); 
      foundfiles = new BindingList<f_results>(y); 
     } 
     catch 
     { } 
    } 

    if (mdate.Text.Trim() != "") 
    { 
     try 
     { 
      List<f_results> y; 
      DateTime test = DateTime.Parse(mdate.Text); 
      if ((mdateop.Text) == ">") 
      { 
       y = (from p in foundfiles where p.mdate >= test select p).ToList(); 
      } 
      else 
       y = (from p in foundfiles where p.mdate <= test select p).ToList(); 
      foundfiles = new BindingList<f_results>(y); 
     } 
     catch 
     { } 
    } 

    if (cdate.Text.Trim() != "") 
    { 
     try 
     { 
      List<f_results> y; 
      DateTime test = DateTime.Parse(cdate.Text); 
      if ((cdateop.Text) == ">") 
      { 
       y = (from p in foundfiles where p.cdate >= test select p).ToList(); 
      } 
      else 
       y = (from p in foundfiles where p.cdate <= test select p).ToList(); 
      foundfiles = new BindingList<f_results>(y); 
     } 
     catch 
     { } 
    } 

最後,我有我的結果,我希望他們的方式,但我正在尋找處理約72   TB文件數據的話,有很多的文件和大量的目錄在我的列表中(totalresults是一個類型的結果,其中包含一個文件列表(f_results)和目錄(結果)..查找然後迭代並返回一個大量的f_results列表匹配給定的正則表達式。

有沒有辦法讓我的LINQ查詢一個查詢?鑑於不是所有的選項都可以使用,例如他們可能只想要文件> x,或者因爲沒有使用..或者..等。

我確實考慮過爲測試製作標誌等等,因爲它是最重要的測試部分。是更好的方式還是更好?或者在洗滌中沒有多大關係?

+0

要加速大輸入處理,您可以使用[Parallel LINQ(PLINQ)](http://msdn.microsoft.com/zh-cn/library/dd460688.aspx)? – sll 2012-03-21 12:39:47

+0

也許,你有我的問題的例子答案(雖然我試圖用棍子戳它,看看我能否用其他方式嗎?) - btw連續linq顯示示例http://msdn.microsoft.com/en-我們/庫/ dd460680。aspx,它並沒有真正涵蓋實際的順序LINQ查詢的方式,這個問題是。 – BugFinder 2012-03-21 12:42:37

+0

我已經讀過一次問題了,所以你希望能夠動態地構建單個LINQ查詢依賴於指定爲字符串的過濾器參數嗎?或者你的主要目標是什麼? – sll 2012-03-21 12:43:51

回答

3

你可以事先生成你的過濾器,然後再應用一次全部 - 你只需要一次迭代您最初的枚舉,像這樣(縮短):

IEnumerable<f_results> foundfiles = new List<f_results>(); 
var filters = new List<Func<f_results, bool>>(); 

if (fsize.Text.Trim() != "") 
{ 
    long sz = long.Parse(fsize.Text); 
    filters.Add(x => x.size >= sz); 
} 

if (adate.Text.Trim() != "") 
{ 
    DateTime test = DateTime.Parse(adate.Text); 
    filters.Add(x => x.adate >= test); 
} 

foreach (var filter in filters) 
{ 
    var filterToApply = filter; 
    foundfiles = foundfiles.Where(filterToApply); 
} 
finalResults = new BindingList<f_results>(foundfiles); 

更重要的是不叫ToList()直到您處理完所有過濾器,否則您會一遍又一遍遍遍遍查看完整的結果列表。

+0

我喜歡這個! (請參閱我將在一秒內添加的評論) – BugFinder 2012-03-21 12:58:40

+1

這非常好。我會將foreach循環更改爲「foundfiles = foundfiles.Where(file => filters.All(filter => filter(file)))」。 – SimpleVar 2012-03-21 12:59:54

+0

謝謝BrokenGlass,我喜歡你的解決方案。我確實找到了一種方法來作爲單個查詢 - 如果有人關心,所以發佈了我自己的答案(見下文),但是,我要調查此問題。我喜歡它。 – BugFinder 2012-03-21 13:09:31

1

至少我建議刪除.ToList()無處不在。作爲LINQ有一個延遲調用,它會遍歷一次,即使你有:

var foundfiles = from p in foundfiles where p.size >= sz select p ; 
foundfiles = from p in foundfiles where p.mdate >= test select p 

更新(在這種情況下,爲了通過都應該過濾後放)

但是,如果你寫:

var foundfiles = (from p in foundfiles where p.size >= sz orderby p.size descending select p).ToList() ; 
foundfiles = (from p in foundfiles where p.mdate >= test select p).ToList(); 

它會迭代兩次 - 這可能是一個嚴重的性能問題。

但我不認爲如果您將此代碼作爲單個查詢,代碼將看起來更簡單。

另外,你爲什麼捕捉所有的例外?你不應該那樣做。

+0

tolien在那裏最初的原因是因爲它可能不會做其他測試。所有這一切都是因爲它的工作正在進行,現在,如果它擰了,我想它繼續並嘗試其餘的:)整潔會晚點來。 – BugFinder 2012-03-21 12:57:51

+0

你可能只有一個ToList()到底:) – Archeg 2012-03-21 13:15:44

1

行 - 我想半回答我的問題..

我可以組合成單一的查詢,以下的作品非常好..理想是什麼?可能不是!

我們現在來看看BrokenGlass的建議,看起來不錯,整齊!

Boolean flag_size = false; 
    Boolean flag_adate = false; 
    Boolean flag_cdate = false; 
    Boolean flag_mdate = false; 
    Int64 sz=0; 
    DateTime adatetest=DateTime.Now; 
    DateTime cdatetest = DateTime.Now; 
    DateTime mdatetest = DateTime.Now; 
    String mop = mdateop.Text; 
    String aop = adateop.Text; 
    String cop = cdateop.Text; 

    if (fsize.Text.Trim() != "") 
    { 
     try 
     { 
      sz = Int64.Parse(fsize.Text); 
      flag_size = true; 
     } 
     catch { } 
    } 

    if (adate.Text.Trim() != "") 
    { 
     try 
     { 
      adatetest = DateTime.Parse(adate.Text); 
      flag_adate = true; 
     } 
     catch 
     { } 
    } 
    if (cdate.Text.Trim() != "") 
    { 
     try 
     { 
      cdatetest = DateTime.Parse(cdate.Text); 
      flag_cdate = true; 
     } 
     catch 
     { } 
    } 
    if (mdate.Text.Trim() != "") 
    { 
     try 
     { 
      mdatetest = DateTime.Parse(mdate.Text); 
      flag_mdate = true; 
     } 
     catch 
     { } 
    } 


    foundfiles = new BindingList<f_results>(totalresults.Find(fname.Text, true)); 


      List<f_results> y = (from p in foundfiles.AsParallel() 
           where (!flag_size || (flag_size && p.size >= sz)) && 
             (!flag_mdate || (flag_mdate && mop == ">" && p.mdate >= mdatetest) || (flag_mdate && mop == "< " && p.mdate >= mdatetest)) && 
             (!flag_adate || (flag_adate && aop == ">" && p.adate >= adatetest) || (flag_adate && aop == "< " && p.adate >= adatetest)) && 
             (!flag_cdate || (flag_cdate && cop == ">" && p.cdate >= cdatetest) || (flag_cdate && cop == "< " && p.cdate >= cdatetest)) 
           orderby p.size descending 
           select p).ToList(); 

      foundfiles = new BindingList<f_results>(y);