2012-01-25 11 views
6

¿Es posible detener un lector en funcionamiento?¿Puedo interrumpir el lector de datos durante la lectura?

Escenario: Tengo una tabla con los datos de 100000 establece

CREATE TABLE stock (
uid bigint NOT NULL, 
name text, 
quantity integer, 
x bytea, 
y bytea 
); 

y una aplicación de consola (.NET 4.0, Npgsql 2.0.11.0/2.0.11.92) para la lectura de datos

conn = new NpgsqlConnection("Server=localhost;Database=postgres;User id=postgres;password=postgres;Timeout=600;CommandTimeout=600;ConnectionLifeTime=600;"); 
using (new ConnectionOpen(conn)) 
using (var ta = conn.BeginTransaction(IsolationLevel.Snapshot)) 
{ 
    IDbCommand command = conn.CreateCommand("SELECT * from stock;"); 
    command.SetTransaction(ta); 
    IDataReader reader = command.ExecuteReader(); 

    int n = 0; 
    while (!reader.IsClosed && reader.Read()) 
    { 
     n++; 

     if (n > 5000) 
     { 
      if (reader != null) 
      { 
       ((NpgsqlDataReader)reader).Close(); 
      } 
     } 
    } 
    ((NpgsqlDataReader)reader).Dispose(); 
    reader = null; 
} 

I han observado que el lector de datos realmente no puede detenerse. Parece que el lector de datos lee todas las filas primero y luego regresa normalmente.

Este ejemplo es un resumen de una aplicación más grande donde el usuario detendrá el lector de datos presionando un botón porque la lectura lleva demasiado tiempo.

Respuesta

0

Puede poner un descanso en el ciclo while, pero no está seguro si/cómo lo vincularía a una acción del usuario para que decida cuándo salir del ciclo de lectura. Alternativamente, podría reestructurar el código para que devuelva el primer número x de filas y luego darles un botón Continuar para devolver el resto o para devolver el siguiente x número de filas.

0

Esto es una suposición.

Posible solución 1

... 
using (var ta = conn.BeginTransaction(IsolationLevel.Snapshot)) 
{ 
    IDbCommand command = conn.CreateCommand("SELECT * from stock;"); 
    command.SetTransaction(ta); 
    IDataReader reader = command.ExecuteReader(); 

    int n = 5000; 

    //put it in using 
    using(IDataReader reader = command.ExecuteReader()) 
    { 
     //read first N rows 
     for(int i=0;i<n;i++) 
     {   
      //get value from the columns of the current row 
      for (i = 0; i < reader.FieldCount; i++) 
      { 
       Console.Write("{0} \t", reader[i]); 
      } 
     } 
    }  
} 

Posible sollution 2

Uso TOP comando sql, see samples

+0

Tengo dejar de lado las salidas de registro en mi escenario.Las salidas de registro para verificar el comportamiento del lector de datos en mi escenario muestran siempre un tiempo de espera después del comando "((lector NpgsqlDataReader)) .Cierre()" de algunos segundos. Este tiempo de espera es casi el mismo si leyera todas las filas. – Joerg

+0

! Verdadero && falso se evalúa como falso. ! verdadero XOR falso se evaluaría como verdadero. –

+0

correcto, actualizará esto. – oleksii

0

El lector de datos típicamente devuelve fragmentos de datos desde el servidor de base de datos (por lo menos así es como funciona con SQL Server). Postgre SQL podría comportarse de manera diferente bajo las cubiertas.

Otra forma de atacar esto es realizar la carga de datos como una tarea en segundo plano (BackgroundWorker, Task, etc.). De esta forma, su hilo de interfaz de usuario se mantiene receptivo y no importa cómo se implemente el lector bajo las cubiertas.

+0

No creo que un BackgroundWorker vaya a funcionar en una aplicación de consola. – LarsTech

+0

Lo he hecho. Pero a veces el usuario desea comenzar una nueva consulta con diferentes datos durante la lectura y la visualización de las primeras filas de datos. Y ahora tengo que detener el lector de datos y comenzar un nuevo comando resp. lector de datos – Joerg

6

Sé que este hilo es bastante antiguo, pero creo que la respuesta correcta a la pregunta de esta persona es el siguiente:

command.Cancel(); //execute before closing the reader 
reader.Close(); 

Llamando DbCommand.Cancel(), que está indicando que no hay más registros deberían ser procesado y que el comando (incluida la consulta subyacente) se detenga inmediatamente y salga rápido. Si no cancela el comando, cuando intenta cerrar el DbDataReader (o salir de un ciclo/usar un bloque), y está tratando con una gran cantidad de registros devueltos, el método Close() completa el valores para parámetros de salida, valor de retorno y registros afectados.

Si intenta cerrar el lector antes de leer todos los registros, Cerrar intenta leer todos los datos y completar esos valores, y parecerá colgarse (lo que probablemente resulte en algún tipo de excepción de tiempo de espera) arrojado). Si no le importan los valores restantes en el conjunto de resultados, y lo más probable es que no lo haga si está saliendo del ciclo de lectura, debe cancelar el comando subyacente antes de llamar a Close().

Partes de la información anterior fue recuperado de: https://www.informit.com/guides/content.aspx?g=dotnet&seqNum=610

+0

Esta es la respuesta –

Cuestiones relacionadas