uso salir for espaƱol definicion codigo bucle array c# .net ado.net

c# - salir - Bucle foreach muy lento



salir de un for c# (6)

Como estábamos hablando en los comentarios, almacenar estos datos en la memoria y trabajar con ellos puede ser un enfoque más eficiente.

Entonces, una manera fácil de hacerlo es comenzar con Entity Framework. Entity Framework generará automáticamente las clases en función de su esquema de base de datos. Luego puede importar un procedimiento almacenado que contiene su instrucción SELECT. La razón por la que sugiero importar un proceso almacenado en EF es que este enfoque generalmente es más eficiente que hacer consultas en LINQ contra EF.

Luego ejecute el proceso almacenado y almacene los datos en una List como esta ...

var data = db.MyStoredProc().ToList();

Entonces puedes hacer lo que quieras con esa data . O como mencioné, si estás haciendo muchas búsquedas en las teclas principales, utiliza ToDictionary() algo como esto ...

var data = db.MyStoredProc().ToDictionary(k => k.MyPrimaryKey);

De cualquier manera, estarás trabajando con tus data en memoria en este momento.

Estoy trabajando en una aplicación existente. Esta aplicación lee datos de un archivo enorme y luego, después de hacer algunos cálculos, almacena los datos en otra tabla.

Pero el ciclo que hace esto (ver abajo) está tomando un tiempo realmente largo. Dado que el archivo a veces contiene miles de registros, todo el proceso lleva días.

¿Puedo reemplazar este ciclo foreach con algo más? Intenté usar Parallel.ForEach y me ayudó. Soy nuevo en esto, por lo que agradeceré su ayuda.

foreach (record someredord Somereport.r) { try { using (var command = new SqlCommand("[procname]", sqlConn)) { command.CommandTimeout = 0; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(…); IAsyncResult result = command.BeginExecuteReader(); while (!result.IsCompleted) { System.Threading.Thread.Sleep(10); } command.EndExecuteReader(result); } } catch (Exception e) { … } }

Después de revisar las respuestas, eliminé Async y usé el código editado como se muestra a continuación. Pero esto no mejoró el rendimiento.

using (command = new SqlCommand("[sp]", sqlConn)) { command.CommandTimeout = 0; command.CommandType = CommandType.StoredProcedure; foreach (record someRecord in someReport.) { command.Parameters.Clear(); command.Parameters.Add(....) command.Prepare(); using (dr = command.ExecuteReader()) { while (dr.Read()) { if () { } else if () { } } } } }


En SQL en el otro extremo de una escritura hay un (un) disco. Raramente puedes escribir más rápido en paralelo. De hecho, en paralelo a menudo lo ralentiza debido a la fragmentación del índice. Si puede ordenar los datos por clave primaria (en clúster) antes de cargarlos. En una gran carga, incluso deshabilitar otras teclas, cargar las claves de reconstrucción de datos.

No estoy muy seguro de lo que se está haciendo en el asynch, pero estoy seguro de que no estaba haciendo lo que esperabas, ya que estaba esperando por sí mismo.

try { using (var command = new SqlCommand("[procname]", sqlConn)) { command.CommandTimeout = 0; command.CommandType = CommandType.StoredProcedure; foreach (record someredord Somereport.r) { command.Parameters.Clear() command.Parameters.Add(…); using (var rdr = command.ExecuteReader()) { while (rdr.Read()) { … } } } } } catch (…) { … }


En lugar de recorrer la conexión sql tantas veces, ¿alguna vez considera extraer todo el conjunto de datos del servidor SQL y procesar los datos a través del conjunto de datos?

Editar: Decidí seguir explicando lo que quise decir ... Puedes hacer lo siguiente, pseudo código como sigue

  1. Utilice una selección * y obtenga toda la información de la base de datos y guárdela en una lista de la clase o diccionario .
  2. Haga su foreach (grabe algunos Grabaciones en algún Informe) y haga la coincidencia de condiciones como de costumbre.

Parece que la ejecución de su comando SQL bloquea algunos de los recursos requeridos y esa es la razón que lo obliga a usar métodos Async (mi suposición).

Si la base de datos no está en uso, intente acceder de forma exclusiva a ella. Incluso cuando hay algunas transacciones internas debido a la complejidad del modelo de datos, considere consultar al diseñador de la base de datos.


Tu mayor problema es que estás revisando esto:

IAsyncResult result = command.BeginExecuteReader(); while (!result.IsCompleted) { System.Threading.Thread.Sleep(10); } command.EndExecuteReader(result);

La idea completa del modelo asíncrono es que el hilo de llamada (el que realiza este ciclo) debe estar girando TODAS las tareas asíncronas utilizando el método Begin antes de comenzar a trabajar con los resultados con el método End. Si está utilizando Thread.Sleep () dentro de su hilo de llamada principal para esperar que se complete una operación asíncrona (como está aquí), lo está haciendo mal, y lo que termina sucediendo es que cada comando, uno a la vez , se lo está llamando y luego se espera antes de que comience el próximo.

En cambio, intente algo como esto:

public void BeginExecutingCommands(Report someReport) { foreach (record someRecord in someReport.r) { var command = new SqlCommand("[procname]", sqlConn); command.CommandTimeout = 0; command.CommandType = CommandType.StoredProcedure; command.Parameters.Add(…); command.BeginExecuteReader(ReaderExecuted, new object[] { command, someReport, someRecord }); } } void ReaderExecuted(IAsyncResult result) { var state = (object[])result.AsyncState; var command = state[0] as SqlCommand; var someReport = state[1] as Report; var someRecord = state[2] as Record; try { using (SqlDataReader reader = command.EndExecuteReader(result)) { // work with reader, command, someReport and someRecord to do what you need. } } catch (Exception ex) { // handle exceptions that occurred during the async operation here } }


Paso 1: Deshazte de la prueba en asincrónico. No está implementado correctamente y está bloqueando de todos modos. Así que solo ejecuta el procedimiento y mira si eso ayuda.

Paso 2: Mueva el SqlCommand fuera del ciclo y reutilícelo para cada iteración. de esta forma, no incurre en el costo de crearlo y destruirlo para cada elemento de su ciclo.

Advertencia: asegúrese de restablecer / borrar / eliminar los parámetros que no necesita de la iteración anterior. Hicimos algo como esto con parámetros opcionales y tuvimos ''purga'' a través de la iteración anterior porque no limpiamos los parámetros que no necesitábamos.