2012-06-13 12 views
10

Quando una libreria esterna contiene un provider LINQ e genera un'eccezione durante l'esecuzione di un albero di espressioni dinamiche, come posso interrompere quando viene generata quell'espressione?Come posso eseguire il debug o impostare un'istruzione break all'interno di un albero di espressioni compilato?

Per esempio, io uso un terzo fornitore LINQ2CRM, che mi permette di chiamare il metodo di IQueryableMax<TSource, TResult>(), ma quando si lancia un InvalidCastException, non riesco a rompere sul posto quando viene generata l'eccezione, rendendo difficile rivedere lo stack-trace perché è già svanito quando il debugger lo interrompe nel mio codice. Ho impostato "break on throw" per l'eccezione citata. Le mie impostazioni di debug sono:

enter image description here


Chiarimento su dove esattamente che vorrei rompere. I non si desidera interrompere l'espressione LINQ, ma, al contrario, voglio interrompere quando viene eseguito l'albero dell'espressione o, in altre parole, quando il metodo di estensione Max() chiama l'override fornito dal provider LINQ. La parte superiore della stacktrace assomiglia a questo, che è dove vorrei spezzare all'interno (o scorrere, o qualsiasi altra cosa):

at XrmLinq.QueryProviderBase.Execute[T](Expression expression) 
at System.Linq.Queryable.Max[TSource,TResult](IQueryable`1 source, Expression`1 selector) 
+0

Vuoi dire attaccare un punto di interruzione in parte di un'espressione lambda in uno di questi metodi? –

+0

Non sono sicuro se [questo aiuti] (http://www.simple-talk.com/dotnet/.net-framework/linq-secrets-revealed-chaining-and-debugging/), ma sto facendo una ricerca ora come questo è interessante. Tutte le strade sembrano andare a LinqPad. Non riesco a vedere come potreste essere in grado di suddividerlo senza il codice sorgente, e poi quando avete il sorgente, non potete semplicemente interromperlo nella parte del provider responsabile di 'Max'? –

+0

La sezione MSDN [Expression Trees] (http://msdn.microsoft.com/en-us/library/bb397951.aspx) ha anche una sezione per [Debugging Expression Trees] (http://msdn.microsoft.com/ it-it/library/ee725345). Penso che sia qui che devo smettere di cercare e tornare al lavoro ;-) –

risposta

4

io non sia la comprensione del problema, ma in realtà invece di rompere sulla linea (che non sembra possibile), sarebbe sufficiente inserire un try-catch all'interno del proprio albero delle espressioni e registrare l'eccezione?

static void Main(string[] args) 
{ 
    var logExceptionMethod = typeof (Program).GetMethod("LogException", BindingFlags.Static | BindingFlags.NonPublic); 
    var createFileMethod = typeof (System.IO.File).GetMethod("Create", new[] {typeof(string)}); 

    // Parameter for the catch block 
    var exception = Expression.Parameter(typeof(Exception)); 

    var expression = 
     Expression.TryCatch(
     Expression.Block(typeof(void), 
      // Try to create an invalid file 
      Expression.Call(createFileMethod, Expression.Constant("abcd/\\"))), 

      // Log the exception from the catch     
      Expression.Catch(exception, Expression.Call(logExceptionMethod, exception))); 

    Expression.Lambda<Action>(expression).Compile()(); 
} 

static void LogException(Exception ex) 
{ 
    Console.WriteLine(ex.Message + "\r\n" + ex.StackTrace); 
} 

uscita della console:

The filename, directory name, or volume label syntax is incorrect. 

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath) 
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) 
at System.IO.File.Create(String path) 
at lambda_method(Closure)