Pregunta

Al recuperar valores de un DataRow, ¿es mejor usar el nombre o el índice de la columna?

El nombre de la columna es más legible y más fácil de mantener:

int price = (int)dr["Price"];

Mientras que el índice de la columna es más rápido (creo):

int price = (int)dr[3];

¿Se rompería el uso de los nombres de columna si decide ofuscar la base de datos?

¿Fue útil?

Solución

Generalmente prefiero la legibilidad y la comprensión sobre la velocidad. Ve con el nombre. Podría (debería) usar constantes de cadena que se pueden actualizar en un lugar si decide cambiar los nombres de columna de la base de datos.

Otros consejos

Acceder a los valores de las columnas / filas a través de los nombres de las columnas es mejor para la lectura humana y la compatibilidad directa (si en el futuro alguien cambia el orden o el recuento de columnas).

Acceder columnas / valores de fila a través de indeces de columna es mejor para el rendimiento.

Entonces, si desea cambiar algún valor en una / dos / ..... filas, los nombres de las columnas están bien. Pero si desea cambiar algún valor en miles de filas, debe usar el índice de columna calculado a partir del nombre de la columna:

int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
    record[ndxMyColumn] = 15;
}

Completamente agresión con otros re. apueste por la legibilidad y el mantenimiento sobre la velocidad. Sin embargo, tenía un método genérico que necesitaba que las columnas con nombre se pasaran como parámetros, por lo que tenía sentido averiguar cuáles eran los índices de las columnas.

En la evaluación comparativa a continuación, el uso del índice de columna mostró una gran mejora, por lo que si se trata de un área de cuello de botella o una parte crítica del rendimiento de su código, puede valer la pena.

El resultado del siguiente código es:

515 ms con ColumnIndex

1031 ms con ColumnName

    static void Main(string[] args)
    {            
        DataTable dt = GetDataTable(10000, 500);
        string[] columnNames = GetColumnNames(dt);

        DateTime start = DateTime.Now;
        TestPerformance(dt, columnNames, true);

        TimeSpan ts = DateTime.Now.Subtract(start);
        Console.Write("{0}ms with ColumnIndex\r\n", ts.TotalMilliseconds);

        start = DateTime.Now;
        TestPerformance(dt, columnNames, false);
        ts = DateTime.Now.Subtract(start);
        Console.Write("{0}ms with ColumnName\r\n", ts.TotalMilliseconds);
    }

    private static DataTable GetDataTable(int rows, int columns)
    {
        DataTable dt = new DataTable();

        for (int j = 0; j < columns; j++)
        {
            dt.Columns.Add("Column" + j.ToString(), typeof(Double));
        }

        Random random = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < rows; i++)
        {
            object[] rowValues = new object[columns];

            for (int j = 0; j < columns; j++)
            {
                rowValues[j] = random.NextDouble();
            }

            dt.Rows.Add(rowValues);
        }

        return dt;
    }

    private static void TestPerformance(DataTable dt, string[] columnNames, bool useIndex)
    {
        object obj;
        DataRow row;

        for (int i =0; i < dt.Rows.Count; i++)
        {
            row = dt.Rows[i];

            for(int j = 0; j < dt.Columns.Count; j++)
            {
                if (useIndex)
                    obj = row[j];
                else
                    obj = row[columnNames[j]];
            }
        }
    }

    private static string[] GetColumnNames(DataTable dt)
    {
        string[] columnNames = new string[dt.Columns.Count];

        for (int j = 0; j < columnNames.Length; j++)
        {
            columnNames[j] = dt.Columns[j].ColumnName;
        }

        return columnNames;
    }

Creo que el nombre de la columna es la mejor manera de hacerlo. Es más fácil determinar lo que está tirando, y el orden de las columnas está determinado por la instrucción select que podría cambiar en algún momento. Se podría argumentar que el nombre de la columna también podría cambiar, pero creo que esto sería mucho menos probable.

EDITAR:

En realidad, si realmente estaba empeñado en usar índices de columna, podría crear constantes de los índices de columna y nombrar la constante como el nombre de la columna. Entonces:

PRIMARY_KEY_COLUMN_NAME_INDEX = 0

Eso al menos lo haría legible.

Depende de lo que necesites. En mi caso, tuve una situación en la que la velocidad era primordial ya que estaba realizando un procesamiento intenso en miles de filas en un DataSet, por lo que decidí escribir un fragmento de código que almacenara en caché los índices de las columnas por nombre. Luego, en el código de bucle, utilicé los índices en caché. Esto dio un aumento de rendimiento razonable sobre el uso del nombre de columna directamente.

Su kilometraje puede variar, por supuesto. Mi situación fue un caso bastante artificial e inusual, pero en ese caso funcionó bastante bien.

Mi opinión es que solo debe cambiar a los índices si ha perfilado su código y se muestra como el cuello de botella. No creo que esto suceda.

Nombrar cosas es bueno, hace que nuestro cerebro limitado comprenda problemas y cree enlaces más fácilmente. Es por eso que se nos dan nombres como Fred, Martin, Jamie, en lugar de Human [189333847], Human [138924342] y Human [239333546].

Si decidió ofuscar la base de datos cambiando los nombres de las columnas en el futuro, podría asignar un alias a esas columnas en su consulta para mantener el código del indexador en funcionamiento. Sugiero indexar por nombre.

Ve con el nombre, obtienes mejores mensajes de error :)

Opto por cadenas para facilitar la lectura y la facilidad de mantenimiento. Utilizo constantes de cadena para definir los valores de los nombres de columna. Ej:

public class ExampleDataColumns
{
    public const string ID = "example_id";
    public const string Name = "example_name";
    ....    
}

Entonces puedo hacer referencia más tarde así:

row[ExampleDataColumns.ID]

Utilice los nombres de columna para DataRow con el mismo token que un RDBMS no ganará velocidad al requerir que los programadores especifiquen el índice de columna en SQL. Pero quizás pueda imitar la forma en que funciona un RDBMS cuando emite una instrucción SELECT, dentro de un motor RDBMS consulta el índice / desplazamiento de las columnas especificadas en la cláusula SELECT antes de atravesar las filas, para que pueda operar más rápido.

Si realmente desea ganar velocidad, no lo haga de manera constante / enum (el orden de las columnas puede cambiar en su base de datos o capa ORM). Hágalo como sugiere TcKs (antes del bucle real):

int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
    record[ndxMyColumn] = 15;
}

para mí, estoy usando la reflexión (no estoy seguro de que sea la forma correcta de nombrar lo que hago) para obtener el columnnameColumn de la tabla

no " codificación rígida " es mejor

  int price = (int)dr[DatableVar.PriceColumn];
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top