Лучше ли использовать имя столбца или индекс столбца в наборах данных .Net?

При извлечении значений из DataRow лучше использовать имя столбца или индекс столбца?

Имя столбца более читабельно и проще в обслуживании:

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

Пока индекс столбца просто быстрее (я думаю):

int price = (int)dr[3];

Не сломается ли использование имен столбцов, если вы решите запутать базу данных?


person tpower    schedule 23.01.2009    source источник


Ответы (11)


Обычно я предпочитаю читабельность и понимание скорости. Иди с именем. Вы можете (должны) использовать строковые константы, которые можно обновлять в одном месте, если вы решите изменить имена столбцов базы данных.

person tvanfosson    schedule 23.01.2009
comment
Я пытался использовать имя - int price = (int)dr[Price]; Я получаю сообщение об ошибке - невозможно неявно преобразовать строку типа в int. Как мне это исправить? Спасибо. - person Steam; 25.02.2014
comment
@blasto - если ваш столбец представляет собой строку, вам нужно использовать int price = int.Parse(dr["Price"]); - person tvanfosson; 25.02.2014
comment
@tvanfosson Вы можете (должны) использовать строковые константы Как насчет использования ColumnName.Name вместо этого? Или есть минусы в этом? - person 41686d6564; 26.08.2016

Доступ к значениям столбцов/строк через имена столбцов лучше для чтения человеком и для прямой совместимости (если в будущем кто-то изменит порядок или количество столбцов).

Доступ к значениям столбцов/строк через индексы столбцов лучше для производительности.

Итак, если вы хотите изменить какое-то значение в одной/двух/..... строках, имена столбцов в порядке. Но если вы хотите изменить какое-то значение в тысячах строк, вы должны использовать индекс столбца, вычисленный из имени столбца:

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

Полностью агрессивен по отношению к другим. отдайте предпочтение удобочитаемости и ремонтопригодности, а не скорости. Однако у меня был общий метод, который должен был передавать именованные столбцы в качестве параметров, поэтому имело смысл выяснить, какие там индексы столбцов.

В приведенном ниже бенчмаркинге использование индекса столбца показало значительное улучшение, поэтому, если это узкое место или критическая для производительности часть вашего кода, это может быть полезно.

Вывод из приведенного ниже кода:

515 мс с ColumnIndex

1031 мс с именем столбца

    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;
    }
person Charlie Openshaw    schedule 13.01.2010

Я думаю, что имя столбца - лучший способ. Легче определить, что вы извлекаете, а порядок столбцов определяется оператором select, который может измениться в будущем. Вы можете возразить, что имя столбца тоже может измениться, но я думаю, что это будет гораздо менее вероятно.

РЕДАКТИРОВАТЬ:

На самом деле, если бы вы действительно стремились использовать индексы столбцов, вы могли бы создать константы индексов столбцов и назвать константу именем столбца. Так:

PRIMARY_KEY_COLUMN_NAME_INDEX = 0

По крайней мере, это сделало бы его читабельным.

person kemiller2002    schedule 23.01.2009
comment
Вы также должны сделать переменную для строки. - person Aaron Fischer; 23.01.2009
comment
На самом деле они, вероятно, должны быть константами, а не переменными. Я бы также обсудил достоинства этого в некоторых случаях, особенно если доступ к набору данных будет осуществляться только в одном месте. Если это изменится позже, это может быть рефакторинг. - person kemiller2002; 23.01.2009

Это зависит от того, что вам нужно. В моем случае у меня была ситуация, когда скорость была первостепенной, поскольку я выполнял интенсивную обработку тысяч строк в наборе данных, поэтому я решил написать фрагмент кода, который кэширует индексы столбцов по имени. Затем в коде цикла я использовал кешированные индексы. Это дало разумный прирост производительности по сравнению с прямым использованием имени столбца.

Конечно, ваш пробег может отличаться. Моя ситуация была довольно надуманной и необычной, но в данном случае она сработала довольно хорошо.

person Andrew Rollings    schedule 23.01.2009

Я считаю, что вам следует переключаться на индексы только в том случае, если вы профилировали свой код, и он оказался узким местом. Я не думаю, что это произойдет.

Именование — это хорошо, это помогает нашему ограниченному мозгу понимать проблемы и легче строить ссылки. Вот почему нам даются такие имена, как Фред, Мартин, Джейми, а не Человек[189333847], Человек[138924342] и Человек[239333546].

person Coincoin    schedule 23.01.2009

Если вы решили запутать базу данных, изменив имена столбцов в будущем, вы можете присвоить этим столбцам псевдонимы в своем запросе, чтобы сохранить работоспособность кода индексатора. Я предлагаю индексировать по имени.

person mqp    schedule 23.01.2009

Идите с именем, вы получите лучшие сообщения об ошибках :)

person Jan Bannister    schedule 23.01.2009

Я выбираю строки для простоты чтения и удобства сопровождения. Я использую строковые константы для определения значений имен столбцов. Бывший:

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

Затем я могу ссылаться на него позже следующим образом:

row[ExampleDataColumns.ID]
person Jim Petkus    schedule 23.01.2009

Используйте имена столбцов для DataRow по тому же признаку, что СУБД не улучшит скорость, требуя от программистов указывать индекс столбца в SQL. Но вы, возможно, можете имитировать способ работы СУРБД, когда вы вводите оператор SELECT, внутри механизма СУРБД он запрашивает индекс столбца/смещение столбцов, указанный в предложении SELECT, прежде чем он пройдет по строкам, чтобы он мог работать быстрее.

Если вы действительно хотите повысить скорость, не используйте метод const/enum (порядок столбцов может измениться в вашей базе данных или на уровне ORM). Сделайте это, как предложил TcKs (перед фактическим циклом):

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

для меня я использую отражение (не уверен, что это правильный способ назвать то, что я делаю), чтобы получить имя столбца из таблицы

никакое "жесткое кодирование" не лучше

  int price = (int)dr[DatableVar.PriceColumn];
person Fredou    schedule 23.01.2009
comment
Но вы по-прежнему предполагаете, что таблица будет содержать определенные столбцы, верно? Как это лучше? - person Kevin Tighe; 23.01.2009
comment
Я использую схемы набора данных, если что-то изменится, по крайней мере, я буду знать, где искать, так как я получу ошибку во время выполнения, а не во время выполнения. - person Fredou; 23.01.2009