NextResult() and so what ?

J’ai parfois du mal à me souvenir du fonctionnement précis de certaines API. Le comportement du IDataReader avec plusieurs résultats en fait partie. Un petit test unitaire s’impose :

[Test]
public void TestDataReaderBehavior()
{
       ExecuteReader( "select 1;",
              delegate( IDataReader r )
       {
             Assert.IsTrue( r.Read(), "We are directly BEFORE the first record." );
             Assert.AreEqual( 1, r.GetInt32( 0 ) );
             Assert.IsFalse( r.Read() );
             Assert.IsFalse( r.Read(), "One can always call Read." );
             Assert.IsFalse( r.NextResult() );
             Assert.IsFalse( r.NextResult(), "One can always call NextResult." );
             Assert.IsFalse( r.IsClosed, "A data reader must explicitely be closed (except if obtained with ExecuteReader( CommandBehavior.CloseConnection )." );
       } );
 
       ExecuteReader( "select 1; select 2;",
              delegate( IDataReader r )
       {
             Assert.IsTrue( r.Read() );
             Assert.AreEqual( 1, r.GetInt32( 0 ) );
             Assert.IsTrue( r.NextResult() );
             Assert.IsTrue( r.Read(), "Here also we are BEFORE the first record." );
             Assert.AreEqual( 2, r.GetInt32( 0 ) );
             Assert.IsFalse( r.Read() );
             Assert.IsFalse( r.NextResult() );
       } );
 
       ExecuteReader( "select 1 from sys.tables where 0=1; select 2;", 
              delegate( IDataReader r )
       {
             Assert.IsFalse( r.Read(), "First select has no results." );
             Assert.IsTrue( r.NextResult() );
             Assert.IsTrue( r.Read() );
             Assert.AreEqual( 2, r.GetInt32( 0 ) );
             Assert.IsFalse( r.Read() );
             Assert.IsFalse( r.NextResult() );
       } );
 
       ExecuteReader( "select 1;select 'Impossible' from sys.tables where 0=1;select 3",
              delegate( IDataReader r )
       {
             Assert.IsTrue( r.Read() );
             Assert.AreEqual( 1, r.GetInt32( 0 ) );
             Assert.IsTrue( r.NextResult(), "There is a 2nd result..." );
             Assert.IsFalse( r.Read(), "...but it is empty." );
             Assert.IsTrue( r.NextResult(), "There is a 3rd result..." );
             Assert.IsTrue( r.Read() );
             Assert.AreEqual( 3, r.GetInt32( 0 ) );
             Assert.IsFalse( r.Read() );
             Assert.IsFalse( r.NextResult() );
             Assert.IsFalse( r.IsClosed );
       } );
}

Cela vaut bien un long discours, non ?
En tous cas, cela vaut mieux que la documentation MSDN ci-dessous qui annonce faussement qu’après l’appel à NextResult, le lecteur est positionné sur le premier enregistrement. J’ai signalé l’erreur (après m’être créé un login .Net passport suite à des années de résistance).

Je vais pouvoir compter les jours avant la correction Smile.
 
Update jeudi 8 octobre 2009 : Il n’y a toujours pas eu de corrections mais une contribution supplémentaire de David Matson qui considère que l’interprétation de la remarque doit se comprendre au niveau de chaque result set et non au niveau des lignes.

Il a complètement raison ce monsieur !