7

从 DataRow 检索值时,使用列名还是列索引更好?

列名更具可读性和更易于维护:

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

虽然列索引更快(我认为):

int price = (int)dr[3];

如果您决定混淆数据库,使用列名会中断吗?

4

11 回答 11

13

我通常更喜欢可读性和理解而不是速度。随名而去。如果您决定更改数据库列名,您可以(应该)使用可以在一处更新的字符串常量。

于 2009-01-23T15:10:04.630 回答
10

通过列名访问列/行值更利于人类阅读和向前兼容性(如果将来有人更改顺序或列数)。

通过列索引访问列/行值对性能更好。

所以,如果你想改变一个/两个/.....行中的一些值,列名是可以的。但是,如果您想更改数千行中的某个值,则应使用从列名计算的列索引:

int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
    record[ndxMyColumn] = 15;
}
于 2009-01-23T15:18:47.343 回答
5

与他人完全侵略。追求可读性和可维护性而不是速度。然而,我有一个通用方法需要将命名列作为参数传入,因此计算列索引是什么是有意义的。

在下面的基准测试中,使用列索引显示了很大的改进,因此如果这是代码的瓶颈区域或性能关键部分,那么它可能是值得的。

下面代码的输出是:

515ms 与 ColumnIndex

1031ms 与 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;
    }
于 2010-01-13T15:23:22.017 回答
3

我认为列名是最好的方法。更容易确定您要提取的内容,并且列顺序由 select 语句确定,该语句可能会在以后的某个时间更改。您可能会争辩说列名也可能会改变,但我认为这不太可能。

编辑:

实际上,如果您真的一心使用列索引,您可以创建列索引的常量并将该常量命名为列的名称。所以:

PRIMARY_KEY_COLUMN_NAME_INDEX = 0

这至少可以使它具有可读性。

于 2009-01-23T15:08:53.807 回答
2

这取决于你需要什么。在我的例子中,我遇到了速度是最重要的情况,因为我正在对 DataSet 中的数千行执行密集处理,因此我选择编写一段按名称缓存列索引的代码。然后,在循环代码中我使用了缓存的索引。与直接使用列名相比,这提供了合理的性能提升。

当然,您的里程可能会有所不同。我的情况是一个相当做作和不寻常的情况,但在那种情况下它运作得相当好。

于 2009-01-23T15:14:47.400 回答
2

我的观点是,只有在分析代码并将其显示为瓶颈时,才应该切换到索引。我不认为这会发生。

命名东西很好,它使我们有限的大脑理解问题并更容易建立链接。这就是为什么我们被命名为 Fred、Martin、Jamie,而不是 Human[189333847]、Human[138924342] 和 Human[239333546]。

于 2009-01-23T15:26:55.423 回答
1

如果您确实决定将来通过更改列名来混淆数据库,则可以在查询中为这些列设置别名以保持索引器代码的功能。我建议按名称索引。

于 2009-01-23T15:10:11.370 回答
1

使用名称,您会收到更好的错误消息:)

于 2009-01-23T15:11:14.067 回答
1

我选择字符串是为了便于阅读和维护。我使用字符串常量来定义列名的值。前任:

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

然后我可以像这样稍后引用它:

row[ExampleDataColumns.ID]
于 2009-01-23T15:27:18.590 回答
1

为 DataRow 使用列名的原因与 RDBMS 不会通过要求程序员在 SQL 中指定列索引来提高速度的原因相同。但是您也许可以在发出 SELECT 语句时模仿 RDBMS 的操作方式,在 RDBMS 引擎内部,它会在遍历行之前查询 SELECT 子句中指定的列的列索引/偏移量,因此它可以更快地运行。

如果您真的想提高速度,请不要使用 const/enum 方式(数据库或 ORM 层上的列顺序可能会更改)。按照 TcKs 的建议进行操作(在实际循环之前):

int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
    record[ndxMyColumn] = 15;
}
于 2009-01-23T15:32:40.530 回答
0

对我来说,我正在使用反射(不确定这是命名我所做工作的正确方法)从表中获取 columnnameColumn

没有“硬编码”更好

  int price = (int)dr[DatableVar.PriceColumn];
于 2009-01-23T15:16:26.023 回答