2009-06-07 47 views
10

Estoy trabajando en Microsoft Visual C# 2008 Express y con SQLite.¿Cómo cuento la cantidad de filas devueltas en mi lector de SQLite en C#?

estoy consultar mi base de datos con algo como esto:

SQLiteCommand cmd = new SQLiteCommand(conn); 

cmd.CommandText = "select id from myTable where word = '" + word + "';"; 
cmd.CommandType = CommandType.Text; 
SQLiteDataReader reader = cmd.ExecuteReader(); 

Entonces hacer algo como esto:

if (reader.HasRows == true) { 
    while (reader.Read()) { 
     // I do stuff here 
    } 
} 

Lo que quiero hacer es contar el número de filas antes de Hago "reader.Read()" ya que el número devuelto afectará lo que quiero/necesito hacer. Sé que puedo agregar un conteo dentro de la declaración while, pero realmente necesito saber el conteo antes.

¿Alguna sugerencia?

Respuesta

23

El DataReader se ejecuta de forma lenta, por lo que no recoge la totalidad del conjunto de filas antes de comenzar. Esto le deja con dos opciones:

  1. iterar y contar
  2. Conde en la instrucción SQL.

Porque yo soy más de un tipo SQL, lo haré el recuento en la instrucción SQL:

cmd.CommandText = "select count(id) from myTable where word = '" + word + "';"; 
cmd.CommandType = CommandType.Text; 
int RowCount = 0; 

RowCount = Convert.ToInt32(cmd.ExecuteScalar()); 

cmd.CommandText = "select id from myTable where word = '" + word + "';"; 
SQLiteDataReader reader = cmd.ExecuteReader(); 

//... 

Nota cómo conté *, no id en el principio. Esto se debe a que count (id) ignorará los id, mientras que count (*) solo ignorará las filas completamente nulas. Si no tiene una identificación nula, use count (id) (es un poco más rápido, dependiendo del tamaño de su tabla).

Actualización: Se ha cambiado a ExecuteScalar, y también cuenta (id) en función de los comentarios.

+0

sí - entre su respuesta y la de Jeremy esto funcionará.Si bien "myTable" será MUY grande con el tiempo, la cantidad de filas devueltas probablemente siempre será pequeña, menos de, digamos, 10, la mayoría de las veces solo será 0-2. ¡Gracias! – adeena

+3

oh - y "id" nunca será nulo. Si es así, algo más está mal. :) – adeena

+0

¿Qué tan grande es "MUY grande" y estás seguro de que SQLite es lo mejor para eso? – Eric

2

Haz una segunda consulta:

 
cmd.CommandText = "select count(id) from myTable where word = '" + word + "';"; 
cmd.CommandType = CommandType.Text; 
SQLiteDataReader reader = cmd.ExecuteReader(); 

Su lector contendrá entonces una sola fila con una columna que contiene el número de filas del conjunto de resultados. El recuento se habrá realizado en el servidor, por lo que debe ser muy rápido.

+0

Tenga cuidado al contar el campo único: si es nulo, no se contará, pero se devolverá. Asegúrese de que un campo tenga una restricción NOT NULL antes de usarlo en un recuento. – Eric

+4

Para contar, debería usar ExecuteScalar que ExecuteReader ... –

+0

Absolutamente. En general, espero que un campo llamado "id" NO ES NULO, pero nunca se puede estar seguro. –

1

Si solo está cargando una columna id de la base de datos, ¿no sería más fácil simplemente cargar en un List<string> y luego trabajar desde allí en la memoria?

+0

Si considera la situación en la que tiene cientos de miles de filas en la tabla, probablemente esto no sea lo que desea hacer. Es mejor ejecutar otra consulta antes de tiempo para encontrar el recuento del conjunto de filas. –

+0

Depende de qué es lo que 'hago aquí' ... según el algoritmo, la mayoría de los datos pueden terminar en la memoria de todos modos. – jerryjvl

+0

También tenga en cuenta que en otro comentario, el remitente indica que normalmente se esperan aproximadamente 10 filas de la consulta, por lo que usar una lista probablemente sea más rápido que dos viajes de ida y vuelta a la base de datos. – jerryjvl

2

Lo que se solicita no es factible - citar Igor Tandetnik, el énfasis es mío:

SQLite produce registros uno por uno, a petición, cada vez que llame sqlite3_step. Simplemente no sabe cuántos va a haber, hasta que en algunos sqlite3_step lo llaman descubre que no hay más.

(sqlite3_step es la función de la API C de SQLite que la interfaz de C# está llamando aquí para cada fila en el resultado).

Usted podría hacer un lugar "SELECT COUNT(*) from myTable where word = '" + word + "';" primero, antes de la consulta "real" - que le dirá el número de filas que va a obtener de la consulta real.

0

pero realmente necesito saber el conteo antes

¿Por qué? esto usualmente no es necesario si usa estructuras de datos en memoria adecuadas (Dataset, List ...). Probablemente haya una manera de hacer lo que quiera que no requiera contar las filas de antemano.

+0

Estoy tratando de implementar una versión del "grabador" que se define aquí: http://www.alicebot.org/documentation/matching.html Básicamente, si hay 0 o 1 filas, tengo una respuesta única y sin preocupaciones . Pero si hay 2 o más filas, entonces tengo que hacer algo más para determinar cuál es la respuesta correcta ... y depende del siguiente nodo en mi "gráfico". ¡Es lo mejor que puedo 'splain en un comentario! :) – adeena

+0

Puede recuperar todas las filas en una lista o conjunto de datos, luego verificar el número de filas y hacer todo lo que necesite hacer en los datos en memoria de acuerdo con el número de filas. A menos que la consulta pueda obtener cientos o miles de filas, eso no debería ser un problema. –

0

Normalmente yo haría

select count(1) from myTable where word = '" + word + "';"; 

para obtener el resultado tan rápido como sea posible. En el caso donde id es un int entonces no hará mucha diferencia. Si fuera algo un poco más grande como un tipo de cadena, notará una diferencia sobre un gran conjunto de datos.

El razonamiento sobre su recuento (1) incluirá las filas nulas. Pero estoy dispuesto a ser corregido si me equivoco al respecto.

0

Usted tiene que contar con select count... from...

Esto hará que su aplicación más lenta. Sin embargo, hay una manera fácil de hacer que tu aplicación sea más rápida y de esa manera se utilizan consultas parametrizadas.

Ver aquí: How do I get around the "'" problem in sqlite and c#?

(Así que además de consultas con parámetros de velocidad tienen otros 2 ventajas también.)

0

probar esto,

SQLiteCommand cmd = new SQLiteCommand(conn); 

cmd.CommandText = "select id from myTable where word = '" + word + "';"; 

SQLiteDataReader reader = cmd.ExecuteReader(); 

while (reader.HasRows) 

    reader.Read(); 

int total_rows_in_resultset = reader.StepCount; 

total_rows_in_resultset le da el número de filas en el resultado después del procesamiento consulta

recuerda que si quieres utilizar el mismo lector, cierra este lector y vuelve a iniciarlo .

0
SQLiteCommand cmd = new SQLiteCommand(conn); 
cmd.CommandText = "select id from myTable where word = '" + word + "';"; 
SQLiteDataReader reader = cmd.ExecuteReader(); 

while (reader.Read()) 
     { 
      total_rows_in_resultset++; 
     } 
+2

Agregue algunas explicaciones de por qué este código ayuda al OP. Esto ayudará a proporcionar una respuesta que los futuros televidentes pueden aprender. Ver [respuesta] para más información. Es especialmente importante al responder preguntas antiguas como esta para diferenciar su respuesta de las muchas otras respuestas preexistentes. –

0

Sin duda, una mejor manera de obtener un recuento de filas sería algo como esto: -

SQLiteDataReader reader = SendReturnSQLCommand(dbConnection, "SELECT COUNT(*) AS rec_count FROM table WHERE field = 'some_value';"); 
     if (reader.HasRows) { 
     reader.Read(); 
     int count = Convert.ToInt32(reader["rec_count"].ToString()); 

... 

    } 

De esa manera usted no tiene que iterar sobre las filas

Cuestiones relacionadas