Replies: 3 comments 2 replies
-
GetValues is generally a bad API, since it forces the driver to internally allocate a new array each time it's used, without allowing for reuse of the array. Users are encouraged to avoid it and read into their own arrays, allowing array reuse across rows. In addition, unless CommandBehavior.SequentialAccess is specified, most ADO.NET buffer the entire row in any case, so DbDataReader.GetValues never needs to perform I/O in any case; that means that GetValueAsync isn't actually need in that case. Regardless, if there's a case for adding such an API, it's preferable to discuss this as a general enhancement to DbDataReader in System.Data (on https://github.com/dotnet/runtime), rather than as a SqlClient-specific feature. |
Beta Was this translation helpful? Give feedback.
-
Thank you for your answer @roji. The application that i built is a bcp export like C# application where I use StringBuilder.AppendFormat applied on the object array return by GetValues. |
Beta Was this translation helpful? Give feedback.
-
Hello @roji , thanks again or you advice against GetValues. I wrote a custom GetString (synchronous) method and remove other async call to return to a synchronous way of doing things. The current version is split into several parts where duration are like that :
May be I could have better performance with asynchronous for all step to fluidify the process ?
The current version look like the following code : using (sqlConnection)
{
var FullFileName = Path.Combine(filePath.ToString(), fileName.ToString());
string vquery = inputsql;
var sw = new StreamWriter(new FileStream(FullFileName, FileMode.Append, FileAccess.Write));
try
{
int crows = 0;
sqlConnection.Open();
DbCommand sqr;
sqr = new SqlCommand(inputsql, sqlConnection as SqlConnection);
using (var sdr = sqr.ExecuteReader())
{
while (sdr.Read())
{
var row = new string[sdr.FieldCount];
for (int i = 0; i < sdr.FieldCount; i++)
{
row[i] = GetString(sdr.GetValue(i), dateformat, useQuoteIdentifier, nfi, typeCodes[i]);
}
sw.WriteLine(string.Join(delimiter, row));
crows++;
}
}
Console.WriteLine($"{DateTime.UtcNow:O} - INFO - file generation completed - {crows} rows in {FullFileName}");
}
catch (Exception e)
{
Console.WriteLine($"{DateTime.UtcNow:O} - ERROR - {e}");
throw;
}
finally
{
sw.Dispose();
}
}
public static string GetString(object objValue, string dateformat, int useQuoteIdentifier, NumberFormatInfo nfi, TypeCode typecode)
{
switch (typecode)
{
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
return objValue.ToString();
case TypeCode.DBNull:
return string.Empty;
case TypeCode.DateTime:
DateTime dt = (DateTime)objValue;
return dt.ToString(dateformat);
case TypeCode.Decimal:
string NumericalFormatDecimal = "0.0###";
var dec = (decimal)objValue;
return dec.ToString(NumericalFormatDecimal, nfi);
case TypeCode.Double:
string NumericalFormatDouble = "0.0#####";
var dbl = (double)objValue;
return dbl.ToString(NumericalFormatDouble, nfi);
default:
if (useQuoteIdentifier == 1)
{
return "\"" + objValue.ToString().Replace("\"", "\\\"") + "\"";
}
else
{
return objValue.ToString();
}
}
}
` |
Beta Was this translation helpful? Give feedback.
-
I think an Async version of GetValues in a DbDataReader could be beneficial.
Something like
Beta Was this translation helpful? Give feedback.
All reactions