2008-12-02 25 views

Respuesta

9

El DataAdapter usa un DataReader bajo el capó para que su experiencia sea la misma.

El beneficio del DataAdapter es que eliminó una gran cantidad de código que necesitaría mantenimiento.

Este debate es un poco de una cuestión religiosa por lo que definitivamente mire a su alrededor y decidir qué funciona mejor para su situación:

+0

Ver mi publicación: eso es menos código que usar un DataAdapter. –

3

No puedo hablar para llenar una tabla de datos por pero el uso de un lector de datos es el método de lectura más eficiente.

+1

Siempre me he preguntado si eso dependía de lo que hacemos con los datos. Dado que DataReader depende del servidor de la base de datos para almacenar la información, en un gran conjunto de resultados, si nuestro cálculo es complejo, como construir un gráfico de red, que se vuelve más difícil con cada nuevo nodo, obstruiría la base de datos. – Haoest

7

Su opción n. ° 1 sería más lenta. Sin embargo, hay una mejor manera de convertir una datareader a una tabla de datos de añadir filas personalizados a mano:

DataTable dt = new DataTable(); 

using (SqlConnection conn = GetOpenSqlConnection()) 
using (SqlCommand cmd = new SqlCommand("SQL Query here", conn) 
using (IDataReader rdr = cmd.ExecuteReader()) 
{ 
    dt.Load(rdr); 
} 

que no puedo comentar sobre la diferencia entre este y el uso de .Fill().

+0

¡Gracias! Estaba buscando cómo cargar una tabla de datos de un lector de datos porque tengo un proceso almacenado que devuelve varias tablas, pero solo necesito 'llenar' una tabla de datos de una de las tablas de salida. – Yoopergeek

1

Es bueno tener DataReader cuando lo que necesita, por ejemplo, muestra el progreso de la carga de datos. En DataSet no puedes hacer algo en medio de cargar datos.

Por otro lado, DataSet es un objeto todo en uno. Entonces DataSet es mucho más lento. DataReader puede darle impulso adicional en lugares en su código donde la operación de datos es muy lenta. En estos lugares, cámbielo de DataSet a DataReader. DataReader también ocupa menos espacio en la memoria.

Por supuesto que lleva más tiempo codificar el buen DataReader, pero vale la pena. Por ejemplo, cuando juegas con imágenes o música tomada desde la base de datos.

More on this topic in MSDN Magazine

2

El datareader es más rápido. Y si usa 2.0+ probablemente no tenga que usar una tabla de datos. Puedes usar una lista genérica de tu objeto.

+1

Su afirmación del año 2008 me ayuda ahora a finales de 2015 :) SqlDataAdapter y SqlDataReader tardan 6.x minutos en cargar DataTable, pero Linq solo tarda 1.7 Segundos en cargar la lista (56460 Filas). –

+0

@PalaniKumar: ¿Puede decirme por favor cómo cargaría directamente el resultado del procedimiento almacenado con la lista usando un lector de datos? –

+1

@Learning, utilicé EntityFramework para obtener el procedimiento almacenado como Lista de objetos. Si desea convertir el lector de datos a la lista, consulte aquí http: // stackoverflow.com/questions/1464883/how-can-i-easily-convert-datareader-to-listt –

11

Suponiendo que realmente desea recuperar todos los datos de la base de datos, es casi seguro que el tiempo transcurrido en la base de datos y en la red empequeñecerá el tiempo necesario para completar las estructuras de datos en la memoria.

Sí, en algunos casos es posible que obtenga un pequeño ahorro utilizando DataReader, y en particular si desea transmitir los datos, puede ser útil, pero si realmente lo necesita todo, me quedaría con el más simple código.Si cree que la población de DataSet está causando un problema de rendimiento significativo, perfilelo y , luego intente mejorarlo.

+0

+1 para "perfilarlo". – Dan

1

Como con muchas preguntas como esta la respuesta es: depende.

Si no conoce la estructura de sus datos por adelantado y está creando TableAdapters sobre la marcha, entonces la DataTable dinámica sería más eficiente. Hay una buena cantidad de generación de código involucrada en la creación de un TableAdapter.

Sin embargo, si conoce la estructura de sus datos por adelantado, entonces la pregunta es: ¿Cuánta funcionalidad necesito?

Si necesita una implementación completa de CRUD, entonces se obtienen algunas eficiencias al usar un TableAdapter en lugar de escribir todo ese código CRUD usted mismo. Además, la implementación de TableAdapter es correcta (no excelente). Si necesita algo más eficiente, es mejor que utilice nHibernate u otro ORM.

Si no necesita una implementación CRUD completa (es decir, esta es una solución de solo lectura) y conoce su estructura de datos por adelantado, entonces deberá probar la eficacia de una implementación de solo lectura TableAdapter contra un DataTable generado dinámicamente Si fuera un apostador, pondría mi dinero en la implementación de TableAdapter, ya que vincula los datos una vez y los lee varias veces.

1

Pasando por DataReaderRead que es un acercamiento solo de reenvío, de una fila a la vez, que lee datos secuencialmente para que pueda obtener registros tan pronto como se leen al conectarse, será el lo mejor para la memoria y el rendimiento.

Dicho esto, entre los dos enfoques, encuentro IDataAdapter.Fill mucho más rápido que DataTable.Load. Por supuesto que depende de las implementaciones .. Aquí es un punto de referencia entre los dos que he publicado here:

public DataTable Read1<T>(string query) where T : IDbConnection, new() 
{ 
    using (var conn = new T()) 
    { 
     using (var cmd = conn.CreateCommand()) 
     { 
      cmd.CommandText = query; 
      cmd.Connection.ConnectionString = _connectionString; 
      cmd.Connection.Open(); 
      var table = new DataTable(); 
      table.Load(cmd.ExecuteReader()); 
      return table; 
     } 
    } 
} 

public DataTable Read2<S, T>(string query) where S : IDbConnection, new() 
              where T : IDbDataAdapter, IDisposable, new() 
{ 
    using (var conn = new S()) 
    { 
     using (var da = new T()) 
     { 
      using (da.SelectCommand = conn.CreateCommand()) 
      { 
       da.SelectCommand.CommandText = query; 
       da.SelectCommand.Connection.ConnectionString = _connectionString; 
       DataSet ds = new DataSet(); //conn is opened by dataadapter 
       da.Fill(ds); 
       return ds.Tables[0]; 
      } 
     } 
    } 
} 

El segundo enfoque siempre superaron a la primera.

Stopwatch sw = Stopwatch.StartNew(); 
DataTable dt = null; 
for (int i = 0; i < 100; i++) 
{ 
    dt = Read1<MySqlConnection>(query); // ~9800ms 
    dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms 

    dt = Read1<SQLiteConnection>(query); // ~4000ms 
    dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms 

    dt = Read1<SqlCeConnection>(query); // ~5700ms 
    dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms 

    dt = Read1<SqlConnection>(query); // ~850ms 
    dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms 

    dt = Read1<VistaDBConnection>(query); // ~3900ms 
    dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms 
} 
sw.Stop(); 
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString()); 

Read1 se ve mejor en los ojos, pero adaptador de datos funciona mejor (no confundir que uno db superó a la otra, las consultas eran todas diferentes). La diferencia entre los dos dependía de la consulta sin embargo. La razón podría ser que Load requiere que se verifiquen varias restricciones fila por fila from the documentation al agregar filas (es un método en DataTable), mientras que Fill está en DataAdapters que fueron diseñados solo para eso: creación rápida de DataTables.

Cuestiones relacionadas