2010-12-01 3 views
13

У меня есть простой LINQ-выражения, как:Обработка исключений в Expression LINQ

newDocs = (from doc in allDocs 
     where GetDocument(doc.Key) != null 
     select doc).ToList(); 

Проблема в том, GetDocument() может вызвать исключение. Как я могу игнорировать все doc-элементы, где GetDocument (doc.Key) == null или генерирует исключение?

Тот же самый код в старой школе выглядит следующим образом:

foreach (var doc in allDocs) 
      { 
       try 
       { 
        if (GetDocument(doc.Key) != null) newDocs.Add(doc); 
       } 
       catch (Exception) 
       { 
        //Do nothing... 
       } 
      } 
+0

Возможный дубликат [Можно ли обрабатывать исключения в запросах LINQ?] (Http://stackoverflow.com/questions/1294251/is-it-possible-to-handle-exceptions-within-linq-queries) – Narkha 2013-09-27 10:21:22

ответ

13
allDocs.Where(doc => { 
    try { 
     return GetDocument(doc.Key) != null; 
    } catch { 
     return false; 
    } 
}).ToList(); 

Я не уверен, что это возможно с помощью синтаксиса на слух запроса, за исключением того, через какой-то барочной злодеяние, как это:

newDocs = (from doc in allDocs 
      where ((Predicate<Document>)(doc_ => { 
       try { 
        return GetDocument(doc_.Key) != null; 
       } catch { 
        return false; 
       } 
      }))(doc) 
      select doc).ToList(); 
+0

Первая часть отлично работает. Я думал, что есть более короткий способ использовать без try/catch. Но это работает и выглядит хорошо. Thanx много – 2010-12-01 09:43:09

11

Вы можете переместить весь блок try catch и GetDocument позвонить по другому методу

Document TryGetDocument(string key) 
{ 
     try 
     { 
      if (GetDocument(doc.Key) != null) 
       return doc; 
     } 
     catch (Exception) 
     { 
      return null; 
     } 
    return null; 
} 

, а затем использовать эту функцию в запросе -

newDocs = (from doc in allDocs 
     where TryGetDocument(doc.Key) != null 
     select doc).ToList(); 

Это будет держать ваш запрос кратким и легким для чтения.

+1

+1: для шаблона TryGetXXX мне лично нравится это при написании кода обработки исключений. – TalentTuner 2010-12-01 08:57:31

1

Напишите ваш собственный метод. MyGetDocument(), который будет обрабатывать исключение и вызывать его из LINQ.

newDocs = (from doc in allDocs 
     where MyGetDocument(doc.Key) != null 
     select doc).ToList(); 
3

Вы пробовали Expression.TryCatch

IEnumerable<string> allDocs = new List<string>(); 
var newDocs = (from doc in allDocs 
        where Expression.TryCatch(
          Expression.Block(GetDocument(doc.key)), 
          Expression.Catch(typeof(Exception),null)) != null         
          select doc).ToList(); 

TryExpression msdn

10

Расширение LINQ можно записать, чтобы пропустить все элементы, которые вызывают исключение. See this stackoverflow post

public static IEnumerable<T> CatchExceptions<T> (this IEnumerable<T> src, Action<Exception> action = null) { 
     using (var enumerator = src.GetEnumerator()) { 
      bool next = true; 

      while (next) { 
       try { 
        next = enumerator.MoveNext(); 
       } catch (Exception ex) { 
        if (action != null) { 
         action(ex); 
        } 
        continue; 
       } 

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

Пример:

ienumerable.Select(e => e.something).CatchExceptions().ToArray() 

ienumerable.Select(e => e.something).CatchExceptions((ex) => Logger.Log(ex, "something failed")).ToArray() 

отправляет это здесь, в случае, если кто-то находит этот ответ первым.

Смежные вопросы