recuperar read mediante executereader ejemplos datos c# linq using datareader yield-return

mediante - sqldatareader to list c#



Me pregunto sobre el estado de la conexión y el impacto en el rendimiento del código por el ''rendimiento'' al iterar sobre el objeto lector de datos (3)

Aquí está mi código de muestra que estoy usando para obtener datos de la base de datos: en la capa DAO:

public IEnumerable<IDataRecord> GetDATA(ICommonSearchCriteriaDto commonSearchCriteriaDto) { using(DbContext) { DbDataReader reader = DbContext.GetReader("ABC_PACKAGE.GET_DATA", oracleParams.ToArray(), CommandType.StoredProcedure); while (reader.Read()) { yield return reader; } } }

En la capa BO estoy llamando al método anterior como:

List<IGridDataDto> GridDataDtos = MapMultiple(_costDriversGraphDao.GetGraphData(commonSearchCriteriaDto)).ToList();

El método MapMultiple de la capa del asignador se define como:

public IGridDataDto MapSingle(IDataRecord dataRecord) { return new GridDataDto { Code = Convert.ToString(dataRecord["Code"]), Name = Convert.ToString(dataRecord["Name"]), Type = Convert.ToString(dataRecord["Type"]) }; } public IEnumerable<IGridDataDto> MapMultiple(IEnumerable<IDataRecord> dataRecords) { return dataRecords.Select(MapSingle); }

El código anterior está funcionando bien y bien, pero me pregunto acerca de dos preocupaciones con el código anterior.

  1. ¿Cuánto tiempo se abrirá la conexión del lector de datos?
  2. Cuando considero el factor de rendimiento del código solamente, ¿es una buena idea usar el ''rendimiento de rendimiento'' en lugar de agregar el registro a una lista y devolver la lista completa?

¿Cuánto tiempo se abrirá la conexión del lector de datos?

La conexión permanecerá abierta hasta que se despida al reader , lo que significa que estará abierta hasta que finalice la iteración.

Cuando considero el factor de rendimiento del código solamente, ¿es una buena idea usar el yield return lugar de agregar el registro a una lista y devolver la lista completa?

Esto depende de varios factores:

  • Si no planea obtener el resultado completo, el yield return le ayudará a ahorrar en la cantidad de datos transferidos en la red
  • Si no planea convertir los datos devueltos en objetos, o si se usan varias filas para crear un solo objeto, el yield return lo ayudará a ahorrar en la memoria utilizada en el punto de uso máximo de su programa.
  • Si planea iterar el conjunto de resultados de recursos durante un corto período de tiempo, no habrá penalizaciones de rendimiento por el uso de la yield return . Si la iteración va a durar una cantidad de tiempo significativa en varios subprocesos concurrentes, la cantidad de cursores abiertos en el lado de RDBMS puede excederse.

  1. su código no muestra dónde abre / cierra la conexión; pero el lector aquí solo estará abierto mientras esté iterando los datos . Ejecución diferida, etc. El único bit de su código que hace esto es el .ToList() , por lo que estará bien. En el caso más general, sí: el lector estará abierto durante el tiempo que tardes en iterarlo; si haces un .ToList() eso será mínimo; Si hace un foreach y (para cada elemento) realiza una solicitud http externa y espera 20 segundos, entonces sí, estará abierto por más tiempo.
  2. Ambos tienen sus usos; el enfoque sin búfer es excelente para los grandes resultados que desea procesar como un flujo, sin tener que cargarlos en una sola lista en la memoria (o incluso tenerlos todos en la memoria a la vez); devolver una lista mantiene la conexión cerrada rápidamente, y facilita evitar el uso accidental de la conexión mientras ya tiene un lector abierto, pero no es ideal para grandes resultados

Si devuelve un bloque de iteradores, la persona que llama puede decidir qué es lo correcto; Si siempre devuelves una lista, no tienen mucha opción. Una tercera forma (que hacemos en apuro) es hacer la elección de ellos; tenemos un parámetro bool opcional que por defecto es "devolver una lista", pero que la persona que llama puede cambiar para indicar "devolver un bloque de iteradores"; básicamente:

bool buffered = true

en los parámetros, y:

var data = QueryInternal<T>(...blah...); return buffered ? data.ToList() : data;

En la implementación. En la mayoría de los casos, devolver una lista es perfectamente razonable y evita muchos problemas, por lo tanto, lo hacemos por defecto.


Esta respuesta ignora las fallas en la implementación mostrada y cubre la idea general.

Es una compensación: es imposible saber si es una buena idea sin conocer las limitaciones de su sistema. ¿Cuál es la cantidad de datos que espera obtener, el consumo de memoria que está dispuesto a aceptar, la carga esperada en la base de datos, etc