2013-10-19 64 views
3

我米使用...異常Linq中處理查詢

tmpLst = (from e in App.lstAllChilds where e.Id == Id select e).ToList(); 

其中lstAllChilds是列表,其中包含了一些被破壞的數據也是如此。

所以現在我試圖在這個查詢中處理Try-Catch塊。
請幫忙。

+0

這是Linq的實體嗎? Linq到對象?什麼是'lstAllChilds'的類型?我無法理解你準確抓住什麼異常......你真的得到了一個嗎? –

+0

我的自定義類列表...(列表 App.lstAllChilds) – Nitin

+0

異常是'InvalidObjectException'和'ArgumentNullException' – Nitin

回答

4

這是您可以做出的最簡單的更改就是排除空值或引發異常的項目。

tmpLst = App.lstAllChilds.Where(e => 
{ 
    try 
    { 
     return e != null && e.Id == Id; 
    } 
    catch 
    { 
     return false; 
    } 
}).ToList(); 

但在我看來,你可能應該調查和解決根本問題。這看起來並不像預期有例外情況。

2

這取決於你正在努力實現的正是:

  1. 返回列表除了「破」的項目。

    • 您可以嘗試使用Where條款檢查並過濾掉:

      App.lstAllChilds.Where(x => IsValidNode(x, Id)).ToList(); 
      

      顯然,你需要實現IsValidNode應檢查null,如果它能夠拋出InvalidObjectException(不知道您可以輕鬆檢測到它,但您始終可以將它包裝在try-catch塊中)和Id等式。這樣的:

      private bool IsValidNode(Child c, int id) 
      { 
          if (x == null) return false; 
          try { 
           return c.Id == id; 
          } 
          catch (InvalidObjectException) 
          { 
      
          } 
          return false; 
      } 
      
  2. 返回一個空列表,如果有任何損壞的物品。

    • 只是包裝整個事情在try-catch塊
8

在情況下,如果你只是想忽略 「壞分子」,則:

App.lstAllChilds.SkipExceptions().Where(e => e.Id == Id).ToList(); 

擴展方法:

public static class Extensions 
    { 
     public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> values) 
     { 
      using (var enumerator = values.GetEnumerator()) 
      { 
       bool next = true; 
       while (next) 
       { 
        try 
        { 
         next = enumerator.MoveNext(); 
        } 
        catch 
        { 
         continue; 
        } 

        if (next) yield return enumerator.Current; 
       } 
      } 
     } 
    } 
3

所以,這是事情。有語言綜合查詢(Linq),然後得到枚舉(又名迭代器)。

Linq允許您定義一個表達式樹,稍後由可能或可能不是C#的東西(例如表達式可以轉換爲SQL查詢)來執行。如果你正在編寫linq,你的查詢提供者(做表達式轉換的東西)不會支持異常處理(更不用說你正在做的事情會拋出異常)。另一方面(或「對象的linq」)的交互只是最終在C#中執行,所以你可以隨意處理異常。

例如瓦特/ LINQ到對象,你可以這樣做:

var myList = new[] { "1", "2", "BARF", "3" }; 
var sum = myList.Select(str => { 
    try { 
    return Int32.Parse(str); 
    } catch { 
    return 0; 
    } 
}).Aggregate((x, y) => x + y); 

如果你確實做的LINQ to對象,你只是想跳過元素,其中源的IEnumerable拋出異常退房弗拉基米爾貢達列夫的回答。

但是務必要了解的重要一點是,我們只是傳遞給選擇呼叫匿名函數不是表達式(未編譯表達式樹),它是一個Func鍵(指向編譯的C#代碼爲代表),這意味着它將運行在.Net進程中,即使我們用一個linq替換myList到實體表(或其他一些linq提供程序)。原因是C#表達式語法不支持塊,也不支持try-catch。不出所料,因爲SQL風格的Linq語句(從xxx選擇yyy)也不支持try-catch塊。

但是,僅僅因爲C#表達式語法不支持它並不意味着你不能這樣做。但是,要清楚,我不建議這樣做,因爲我非常懷疑存在支持它的QueryProvider(除了linq to objects provider)。好奇的是,你將如何創建一個包含try-catch塊的lambda表達式。

var parseMethod = typeof(Int32).GetMethod("Parse", new[] { typeof(String) }); 
var param = Expression.Parameter(typeof(String)); 
var selectExp = 
    Expression.Lambda<Func<String, Int32>>(
     Expression.TryCatch(
      Expression.Call(parseMethod, param), 
      Expression.Catch(typeof(Exception), Expression.Constant(0)) 
     ), 
     param 
    ); 
var sum = myList.Select(selectExp).Aggregate((x, y) => x + y); 

因此,當有人實現由支持異常處理的存儲支持的QueryProvider時,您可以使用它。