executereader - sqldatareader c# ejemplos
¿Cuál es la forma más rápida de leer datos de un DbDataReader? (6)
En el siguiente código, el comando es un DbCommand que ya se ha configurado:
using( var dataReader = command.ExecuteReader() /*The actual execution of the query takes relatively little time.*/ ) {
while( dataReader.Read() ) {
// These are what take all of the time. Replacing them all with reader.GetValues( myArray ) has no impact.
val0 = dataReader.GetValue( 0 );
val1 = dataReader.GetValue( 1 );
val2 = dataReader.GetValue( 2 );
}
}
La mayor parte del tiempo para la consulta con la que estoy trabajando actualmente se dedica a realizar las llamadas GetValue. ¿Está realizando un viaje de ida y vuelta a la base de datos para cada llamada GetValue? Parece que lo es, y esto parece muy ineficiente. Como lo indica el código, intentar hacerlo de una sola vez con GetValues () no hace una diferencia. ¿Hay una manera de obtener toda la fila en un tiro? Mejor aún, ¿hay una manera de obtener todo el conjunto de resultados en una sola toma?
Gracias.
Hice algunos puntos de referencia con varios enfoques:
public DataTable Read1(string query)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
var table = new DataTable();
using (var r = cmd.ExecuteReader())
table.Load(r);
return table;
}
}
public DataTable Read2<S>(string query) where S : IDbDataAdapter, IDisposable, new()
{
using (var da = new S())
{
using (da.SelectCommand = conn.CreateCommand())
{
da.SelectCommand.CommandText = query;
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0];
}
}
}
public IEnumerable<S> Read3<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
while (r.Read())
yield return selector(r);
}
}
public S[] Read4<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
return ((DbDataReader)r).Cast<IDataRecord>().Select(selector).ToArray();
}
}
public List<S> Read5<S>(string query, Func<IDataRecord, S> selector)
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.Open();
using (var r = cmd.ExecuteReader())
{
var items = new List<S>();
while (r.Read())
items.Add(selector(r));
return items;
}
}
}
1 y 2 devuelve DataTable
mientras que el resto tipificó el conjunto de resultados, por lo que no es exactamente de manzana a manzana, sino que las cronometré en consecuencia.
Sólo lo esencial:
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
Read1(query); // ~8900 - 9200ms
Read1(query).Rows.Cast<DataRow>().Select(selector).ToArray(); // ~9000 - 9400ms
Read2<MySqlDataAdapter>(query); // ~1750 - 2000ms
Read2<MySqlDataAdapter>(query).Rows.Cast<DataRow>().Select(selector).ToArray(); // ~1850 - 2000ms
Read3(query, selector).ToArray(); // ~1550 - 1750ms
Read4(query, selector); // ~1550 - 1700ms
Read5(query, selector); // ~1550 - 1650ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
La consulta devolvió aproximadamente 1200 filas y 5 campos (se ejecutó 100 veces). Aparte de Read1
todo funcionó bien. De todos, prefiero Read3
que devuelve datos perezosamente, como se enumera. Esto es genial para la memoria si solo necesitas enumerarlo. Para tener una copia de la colección en la memoria, le Read4
Read5
Read4
o Read5
como le plazca.
Podría usar un DbDataAdapter
para obtener todos los resultados y almacenarlos en un DataTable
.
Utilice DataSet sin tipo. Eso es lo más rápido, que yo sepa.
dapper-dot-net algo como dapper-dot-net para cargarlo en un modelo de tipo básico; este es un micro-ORM, por lo que obtiene los beneficios de la meta-programación (IL pre-generada de manera eficiente, etc.) - sin la sobrecarga de cosas como EF o DataTable.
Dim adapter As New Data.SqlClient.SqlDataAdapter(sqlCommand)
Dim DT As New DataTable
adapter.Fill(DT)
using (connection)
{
SqlCommand command = new SqlCommand(
"SELECT CategoryID, CategoryName FROM dbo.Categories;" +
"SELECT EmployeeID, LastName FROM dbo.Employees",
connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.HasRows)
{
Console.WriteLine("/t{0}/t{1}", reader.GetName(0),
reader.GetName(1));
while (reader.Read())
{
Console.WriteLine("/t{0}/t{1}", reader.GetInt32(0),
reader.GetString(1));
}
reader.NextResult();
}
}