在.Net DataSet上使用列名或列索引更好吗?

时间:2009-01-23 15:07:41

标签: .net dataset obfuscation datarow

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

列名更易读,更易于维护:

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

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

int price = (int)dr[3];

如果您决定对数据库进行模糊处理,是否会使用列名中断?

11 个答案:

答案 0 :(得分:13)

我通常更喜欢可读性和对速度的理解。跟着名字去吧。如果您决定更改数据库列名,则可以(应该)使用可在一个位置更新的字符串常量。

答案 1 :(得分:9)

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

通过列indeces赋予列/行值更好的性能。

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

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

答案 2 :(得分:4)

与其他人完全一致。追求速度的可读性和可维护性。然而,我有一个通用的方法,需要将命名列作为参数传入,所以有意义的是找出列索引是什么。

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

以下代码的输出是:

使用ColumnIndex

515毫秒

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;
    }

答案 3 :(得分:3)

我认为列名是最好的方法。您可以更轻松地确定要拉动的内容,并且列顺序由select语句确定,该语句可能会在某个时间发生变化。你可能会争论列名也可能会改变,但我认为这样的可能性会小得多。

编辑:

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

PRIMARY_KEY_COLUMN_NAME_INDEX = 0

这至少会让它变得可读。

答案 4 :(得分:2)

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

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

答案 5 :(得分:2)

我的意见是,如果您对代码进行了分析并且它显示为瓶颈,那么您应该只切换到索引。我认为这不会发生。

命名的东西很好,它使我们有限的大脑理解问题并更容易建立链接。这就是为什么我们被赋予像弗雷德,马丁,杰米,而不是人类[189333847],人类[138924342]和人类[239333546]。

答案 6 :(得分:1)

如果您决定通过在将来更改列名来对数据库进行模糊处理,则可以在查询中对这些列进行别名以保持索引器代码的功能。我建议按名称编制索引。

答案 7 :(得分:1)

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

答案 8 :(得分:1)

我选择字符串以方便阅读和维护。我使用字符串常量来定义列名的值。例如:

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

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

row[ExampleDataColumns.ID]

答案 9 :(得分:1)

使用DataRow的列名称,使RDBMS无法通过要求程序员在SQL中指定列索引来获得速度。但是,您可以模仿RDBMS在发出SELECT语句时的操作方式,在RDBMS引擎中它在遍历行之前查询SELECT子句中指定的列的列索引/偏移量,因此它可以更快地运行。

如果你真的想提高速度,那么不要以const / enum方式执行(列顺序可能会在您的数据库或ORM层上发生变化)。像TcKs建议的那样(在实际循环之前):

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

答案 10 :(得分:0)

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

没有“硬编码”更好

  int price = (int)dr[DatableVar.PriceColumn];