//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// DataHelpers.SQL satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Data.SqlClient;
using u = user_rtx;

namespace DataHelpers.SQL {

partial class HQueryExecContextBase {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>> RSetToList_A<RSet_Item>( SqlDataReader dataReader,
                                                             bool closeReader = false )
where RSet_Item: new() =>
   RSetToListX_A<RSet_Item>( null, dataReader, closeReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>> RSetToList_A<RSet_Item>( [u.positive] int resultSetNo,
                                                             SqlDataReader dataReader,
                                                             bool closeReader = false )
where RSet_Item: new() =>
   RSetToListX_A<RSet_Item>( resultSetNo, dataReader, closeReader );
/// <exception cref="ArgumentOutOfRangeException" />
/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>> RSetToListX_A<RSet_Item>( [u.positive] int? resultSetNo,
                                                                    SqlDataReader dataReader,
                                                                    bool closeReader = false )
where RSet_Item: new()
{
   if ( resultSetNo.HasValue )
      u.arg_check.Positive( resultSetNo.Value, nameof(resultSetNo) );
   await EnsureConnected_A().ConfigureAwait(false);
   void disposeReader() {
      if ( closeReader ){
         dataReader.Close();
         dataReader.Dispose();
      }};
   List<RSet_Item> list;
   var curr = Current;
   curr._dataReader = dataReader;
   try {
      VerifyFieldCountX( resultSetNo, dataReader );
      list = new List<RSet_Item>();
      while ( await dataReader.ReadAsync().ConfigureAwait(false) )
         list.Add( new RSet_Item() );
   }
   catch {
      u.ops.Try( disposeReader );
      throw;
   }
   finally {
      curr._dataReader = null;
   }
   disposeReader();
   return list;
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>?> RSetToListOrNull_A<RSet_Item>( SqlDataReader dataReader,
                                                                          bool closeReader = false )
where RSet_Item: new()
{
   await EnsureConnected_A().ConfigureAwait(false);
   void disposeReader() {
      if ( closeReader ){
         dataReader.Close();
         dataReader.Dispose();
      }};
   List<RSet_Item>? list = null;
   var curr = Current;
   curr._dataReader = dataReader;
   try {
      if ( dataReader.FieldCount > 0 )
      {
         list = new List<RSet_Item>();
         while ( await dataReader.ReadAsync().ConfigureAwait(false) )
            list.Add( new RSet_Item() );
      }
   }
   catch {
      u.ops.Try( disposeReader );
      throw;
   }
   finally {
      curr._dataReader = null;
   }
   disposeReader();
   return list;
}

//==================================================================================================

/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>?> NakedDoReaderCommand_A<RSet_Item>( SqlCommand command )
where RSet_Item: new() =>
   NakedDoReaderCommandX_A<RSet_Item>( null, command );

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>?> NakedDoReaderCommand_A<RSet_Item>( string commandText )
where RSet_Item: new() =>
   NakedDoReaderCommandX_A<RSet_Item>( null, commandText );
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>?> NakedDoReaderCommand_A<RSet_Item>(
   string commandText, params SqlParameter[] sqlParams )
where RSet_Item: new() =>
   NakedDoReaderCommandX_A<RSet_Item>( null, commandText, sqlParams );

//--------------------------------------------------------------------------------------------------

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static Task<List<RSet_Item>?> NakedDoReaderCommandFmt_A<RSet_Item>(
   string commandTextFmt, params object?[] args )
where RSet_Item: new() =>
   NakedDoReaderCommandFmtX_A<RSet_Item>( null, commandTextFmt, args );

//==================================================================================================

/// <exception cref="ArgumentException" />
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>?> NakedDoReaderCommandX_A<RSet_Item>(
   Action? beforeScan, SqlCommand command )
where RSet_Item: new()
{
   await EnsureConnected_A().ConfigureAwait(false);
   var rdr = await HSqlCommandDispose.ExecuteReader_A( command ).ConfigureAwait(false);
   beforeScan?.Invoke();
   return await RSetToListOrNull_A<RSet_Item>( rdr, true ).ConfigureAwait(false);
}

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>?> NakedDoReaderCommandX_A<RSet_Item>(
   Action? beforeScan, string commandText )
where RSet_Item: new()
{
   await EnsureConnected_A().ConfigureAwait(false);
   var rdr = await new HSqlOperator(Connection).ExecuteReader_A(
      OuterTransaction, commandText ).ConfigureAwait(false);
   beforeScan?.Invoke();
   return await RSetToListOrNull_A<RSet_Item>( rdr, true ).ConfigureAwait(false);
}
/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>?> NakedDoReaderCommandX_A<RSet_Item>(
   Action? beforeScan, string commandText, params SqlParameter[] sqlParams )
where RSet_Item: new()
{
   await EnsureConnected_A().ConfigureAwait(false);
   var rdr = await new HSqlOperator(Connection).ExecuteReader_A(
      OuterTransaction, commandText, sqlParams ).ConfigureAwait(false);
   beforeScan?.Invoke();
   return await RSetToListOrNull_A<RSet_Item>( rdr, true ).ConfigureAwait(false);
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="InvalidOperationException" />
[u.async_local]
public static async Task<List<RSet_Item>?> NakedDoReaderCommandFmtX_A<RSet_Item>(
   Action? beforeScan, string commandTextFmt, params object?[] args )
where RSet_Item: new()
{
   await EnsureConnected_A().ConfigureAwait(false);
   var rdr = await new HSqlOperator(Connection).ExecuteReaderFmt_A(
      OuterTransaction, commandTextFmt, args ).ConfigureAwait(false);
   beforeScan?.Invoke();
   return await RSetToListOrNull_A<RSet_Item>( rdr, true ).ConfigureAwait(false);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HQueryExecContextBase

} // DataHelpers.SQL
