Proposed Answer FromAsyncPattern and SQLDataReader

  • Wednesday, January 09, 2013 5:50 PM
     
      Has Code

    Hi

    I'm trying to use the above pattern to wrap the sqldatareader. The last line below is causing a problem

    Using cmd = connection.CreateCommand
          cmd.CommandType = CommandType.Text
          cmd.CommandText = script.ToSql(New SqlServerWriter)
          connection.Open()
          Dim asyncReader = Observable.FromAsyncPattern(Of SqlDataReader)(cmd.BeginExecuteReader, cmd.EndExecuteReader)

    since the VB compiler is complaining that EndExecuteReader needs an argument for parameter asyncResult. I have checked several C# examples which don't seem to have such a parameter. 

    Must be something obviously I'm missing. If someone could point me to a correct VB implementation here, I'd be grateful.

    Many thx

    S



    • Edited by Simon Woods Wednesday, January 09, 2013 5:54 PM Added more code
    • Edited by Simon Woods Wednesday, January 09, 2013 5:55 PM Formatting
    •  

All Replies

  • Wednesday, January 09, 2013 9:51 PM
     
     Proposed Answer Has Code

    Hi, 

    > the VB compiler is complaining that EndExecuteReader needs an argument for parameter asyncResult

    Here's the signature of EndExecuteReader according to the documentation:

    http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.endexecutereader.aspx

    public SqlDataReader EndExecuteReader(IAsyncResult asyncResult)

    Clearly there's an IAsyncResult parameter.  (I checked all versions of the .NET Framework to be sure, since you didn't specify a version.)

    So the problem must be with overload resolution of FromAsyncPattern.

    The only other argument is BeginExecuteReader, so let's have a look at that.  Each version of the .NET Framework has 4 overloads.  Here are the signatures according to the documentation:

    http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutereader.aspx

    IAsyncResult BeginExecuteReader()
    IAsyncResult BeginExecuteReader(CommandBehavior)
    IAsyncResult BeginExecuteReader(AsyncCallback, Object)
    IAsyncResult BeginExecuteReader(AsyncCallback, Object, CommandBehavior)

    The latter two meet the requirements for the APM.  Perhaps they're ambiguous for overload resolution of FromAsyncPattern, or the compiler is simply choosing the wrong one.  So let's see what overloads of FromAsyncPattern are candidates...

    You're specifying a single generic type argument, so here are the signatures (excluding return types) of FromAsyncPattern that have a single generic type argument according to the documentation:

    http://msdn.microsoft.com/en-us/library/hh229919(v=vs.103).aspx

    FromAsyncPattern<TResult>(Func<AsyncCallback, Object, IAsyncResult>, Func<IAsyncResult, TResult>)
    FromAsyncPattern<T1>(Func<T1, AsyncCallback, Object, IAsyncResult>, Action<IAsyncResult>)

    Looking at the number and order of the parameters, it seems that only the first signature is a valid match and it can only correspond to the third signature of BeginExecuteReader:

    IAsyncResult BeginExecuteReader(AsyncCallback, Object)

    Note that the second signature doesn't match the fourth signature of BeginExecuteReader because CommandBehavior is in the wrong place, which would put Object where AsyncCallback is expected, though it has the correct number of generic type arguments.

    So it looks like we've got our winner.  But to my surprise, it also matches the signature of EndExecuteReader.

    IAsyncResult BeginExecuteReader(AsyncCallback, Object)
    SqlDataReader EndExecuteReader(IAsyncResult asyncResult)
    FromAsyncPattern<TResult>(Func<AsyncCallback, Object, IAsyncResult>, Func<IAsyncResult, TResult>)

    Obviously, I didn't try this in Visual Studio.  If you place the mouse cursor over FromAsyncPattern, which overload does IntelliSense show that the compiler is choosing?

    - Dave


    http://davesexton.com/blog

    • Edited by Dave Sexton Wednesday, January 09, 2013 9:54 PM Clarification
    • Proposed As Answer by Mr. Javaman II Thursday, January 17, 2013 7:10 PM
    •  
  • Thursday, January 10, 2013 9:15 AM
     
     Proposed Answer Has Code

    Dave

    Once again, thx very much. The overload being used was

    FromAsyncPattern(Of TResult)(begin As Func(Of AsyncCallback, Object, IAsyncResult), end As Func(of IAsyncResult, TResult) As IObservable(Of TResult)

    So I mod'ed my code to

    Dim asyncReader = Observable.FromAsyncPattern(Of SqlDataReader)(Function(ac, o) cmd.BeginExecuteReader(ac, o), Function(ar) cmd.EndExecuteReader(ar))

    and it is fine, now.

    I guess it is just the way that, in VB parlance, 'lambda' subs and functions can be inferred implicitly in C# but needs a bit more coaxing in VB. 

    Thx for talking me thru it again.

    S


    • Edited by Simon Woods Thursday, January 10, 2013 9:17 AM clarification
    • Proposed As Answer by Dave Sexton Thursday, January 10, 2013 2:12 PM
    •