Dealing with nulls and exceptions in query syntax

If I want to dump the running processes where the company name is Microsoft I have to write a somewhat grody query:



var msProcesses =
    from p in processes
    where p.Id > 4 &&
          p.MainModule.FileName.IndexOf(' ') == -1 &&
          p.MainModule.FileVersionInfo.CompanyName != null &&
          p.MainModule.FileVersionInfo.CompanyName.StartsWith("Microsoft")
    select new { p.MainModule.ModuleName,
                 p.MainModule.FileVersionInfo.CompanyName };

 


If you ask for certain properties on the System or Idle processes you get exceptions and certain processes don't have a company name specified.  It might be nice to have a way to coalesce nulls (kind of like Lisp or ObjC does).  Is there a way to catch exceptions within the query syntax so that I can ignore certain exceptions and continue processing the query or am I stuck writing a lot of defense code in my query



Answer this question

Dealing with nulls and exceptions in query syntax

  • wiz

    Funny you should ask...

    I started working today on a way to encapsulate retry/ignore/abort/throw logic in IEnumerable<T>.

    example:


    foreach (byte b in GetBytesWithTimeout(port, maxBytes, RecoveryStrategies.RetryNTimesThenAbort(maxRetries)))
    {
       Console.Write("{0:x2} ", b);
    }


     



    where


    public static RecoveryStrategy<SerialPortReaderState, FullRecoveryOption> RetryNTimesThenAbort(int n)
    {
       
    return
          
    delegate(Exception ex, SerialPortReaderState state)
          {
             
    if (state.RetriesAttempted < n)
             {
                state.RetriesAttempted++;

                
    return FullRecoveryOption.Retry;
             }
             else
             
    {
                
    return FullRecoveryOption.Abort;
             }
          };
    }


     

    and


    static IEnumerable<byte> GetBytesWithTimeout(SerialPort port, int maxBytes, RecoveryStrategy<SerialPortReaderState, FullRecoveryOption> recoveryStrategy)
    {
       
    SerialPortReaderState state = new SerialPortReaderState();

       
    int byteCount = 0;

       
    while (byteCount < maxBytes)
       {
          
    byte b = 0;

          
    try
          
    {
             
    int read = port.BaseStream.ReadByte();

             b = (
    byte)read;
          }
          
    catch (Exception ex)
          {
             
    Console.WriteLine("Exception Encountered: {0}", ex.Message);

             
    FullRecoveryOption recoveryOption = recoveryStrategy(ex, state);

             
    if (recoveryOption == FullRecoveryOption.Retry)
             {
                
    Console.WriteLine("Retrying: # attempts = {0}", state.RetriesAttempted);

                
    continue;
             }
             
    else if (recoveryOption == FullRecoveryOption.RaiseException)
             {
                
    throw ex;
             }
             
    else if (recoveryOption == FullRecoveryOption.Abort)
             {
                
    Console.WriteLine("in Abort");

                
    yield break;
             }
             
    else if (recoveryOption == FullRecoveryOption.Ignore)
             {
                
    continue;
             }
          }

          byteCount++;

          
    yield return (byte)b;
       }
    }


     



    Oddly, I seem to have encounted a strange bug in the debugger or compiler, where if I issue the continue in that if/else/if block in GetBytesWithTimeout, it'll actually jump to the yield break for FullRecoveryOption.Abort (skipping the Console.WriteLine on the previous line) before looping back.  It behaves the same if it's a switch block.

    I'm being coerced into turning this into an article somewhere, but it needs more time to simmer.



  • Larry Guger

    I wonder if the coolest feature to come out of LINQ is the fact that it is extensible.  Nice extension!


  • tomahawk009

    I haven't started dealing with LINQ on this, but it should be usable from there as a wrapper to some other data source.

    Actually, I've been dealing mostly with querying cell phones for their debug logs (my company writes cell phone software -- anybody here using a Samsung A840 ).

  • Dealing with nulls and exceptions in query syntax