read executereader c# ado.net idatareader

executereader - mysqldatareader c#



IDataReader y "HasColumn", ¿el mejor enfoque? (3)

He visto dos enfoques comunes para verificar si existe una columna en un IDataReader:

public bool HasColumn(IDataReader reader, string columnName) { try { reader.getOrdinal(columnName) return true; } catch { return false; } }

O:

public bool HasColumn(IDataReader reader, string columnName) { reader.GetSchemaTable() .DefaultView.RowFilter = "ColumnName=''" + columnName + "''"; return (reader.GetSchemaTable().DefaultView.Count > 0); }

Personalmente, he usado el segundo, ya que odio usar excepciones por este motivo.

Sin embargo, en un gran conjunto de datos, creo que RowFilter podría tener que hacer un escaneo de tabla por columna, y esto puede ser increíblemente lento.

¿Pensamientos?


Mucho depende de cómo uses HasColumn. ¿Lo está llamando solo una o dos veces, o repetidamente en un bucle? ¿Es probable que la columna esté allí o es completamente desconocida de antemano?

Establecer un filtro de fila probablemente haría un escaneo de tabla cada vez. (Además, en teoría, GetSchemaTable () podría generar una tabla completamente nueva con cada llamada, lo que sería aún más caro: no creo que SqlDataReader lo haga, pero a nivel de IDataReader, ¿quién sabe?) Pero si solo Llámalo una o dos veces. No puedo imaginar que esto sea un problema (a menos que tengas miles de columnas o algo así).

(Sin embargo, al menos almacenaría el resultado de GetSchemaTable () en una var local dentro del método para evitar llamarlo dos veces en una sucesión rápida, si no lo almacené en caché en algún lugar con la posibilidad de que su particular IDataReader LO HAGA volver a generar).

Si sabe de antemano que en circunstancias normales la columna que solicita estará presente, el método de excepción es un poco más aceptable (porque la columna que no está allí es, de hecho, un caso excepcional). Incluso si no, podría funcionar un poco mejor, pero de nuevo, a menos que lo llames repetidamente, deberías preguntarte si el rendimiento es realmente una gran preocupación.

Y si lo está llamando repetidamente, probablemente deba considerar un enfoque diferente de todos modos, como: llamar a GetSchemaTable () una vez por adelantado, recorrer la tabla y cargar los nombres de campo en un diccionario u otra estructura que esté diseñada para rápido búsquedas.


No me preocuparía el impacto en el rendimiento. Incluso si tuviera una tabla con 1000 columnas (que sería una tabla enorme), todavía solo está haciendo un "escaneo de tabla" de 1000 filas. Eso es probable que sea trivial.

La optimización prematura lo llevará a una implementación innecesariamente compleja. Implemente la versión que le parezca mejor y luego mida el impacto en el rendimiento. Si no es aceptable en comparación con sus requisitos de rendimiento, entonces considere alternativas.


Creo que tengo una respuesta razonable para esta vieja gema.

Me gustaría ir con el primer enfoque porque es mucho más simple. Si desea evitar la excepción, puede almacenar en caché los nombres de los campos y hacer un TryGet en el caché.

public Dictionary<string,int> CacheFields(IDataReader reader) { var cache = new Dictionary<string,int>(); for (int i = 0; i < reader.FieldCount; i++) { cache[reader.GetName(i)] = i; } return cache; }

Lo bueno de este enfoque es que es más simple y te da un mejor control. Además, tenga en cuenta que es posible que desee buscar insensibles a las mayúsculas y minúsculas o insensibles a kana, lo que haría las cosas un poco más complicadas.