2010-12-01 16 views
13

que tiene un simple LINQ-expresión como:El manejo de excepciones dentro de una expresión LINQ

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

El problema es, GetDocument() podría lanzar una excepción. ¿Cómo puedo ignorar todos los elementos de documento donde GetDocument (doc.Key) == null o lanza una excepción?

El mismo código en la vieja escuela se ve como:

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

posible duplicado de [¿Es posible manejar excepciones dentro de consultas LINQ?] (Http://stackoverflow.com/questions/1294251/is-it-possible-to-handle-exceptions-within-linq-queries) – Narkha

Respuesta

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

No estoy seguro de que es posible utilizando la sintaxis de la comprensión de consulta, excepto a través de alguna atrocidad barroca como esto:

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

La primera parte funciona a la perfección. Pensé que hay una forma más corta de usar sin try/catch. Pero funciona y se ve bien. Gracias mucho –

11

Puede mover el bloque completo try catch y GetDocument llamar a otro método

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

y luego utilizar esta función en su consulta -

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

Esto mantendrá su consulta concisa y fácil de leer.

+1

+1: para el patrón TryGetXXX, personalmente me gusta mientras escribo el código de manejo de excepciones. – TalentTuner

1

Escriba su propio método. MyGetDocument() que manejará la excepción y la llamará desde LINQ.

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

Ha intentado la 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

Una extensión de LINQ se puede escribir para saltar todos los elementos que causan una excepción. 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; 
       } 
      } 
     } 
    } 

Ejemplo:

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

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

publicar esto aquí por si alguien más se encuentra esta respuesta en primer lugar.