oracledatareader executereader example ejemplos data c# .net database

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(); } }