DataRow から値を取得する場合、列名または列インデックスを使用する方が適切ですか?
列名はより読みやすく、維持しやすくなっています。
int price = (int)dr["Price"];
列インデックスの方が高速ですが(私はそう思います):
int price = (int)dr[3];
データベースを難読化することにした場合、列名を使用すると壊れますか?
DataRow から値を取得する場合、列名または列インデックスを使用する方が適切ですか?
列名はより読みやすく、維持しやすくなっています。
int price = (int)dr["Price"];
列インデックスの方が高速ですが(私はそう思います):
int price = (int)dr[3];
データベースを難読化することにした場合、列名を使用すると壊れますか?
私は一般的に、スピードよりも読みやすさと理解を好みます。名前で行きます。データベースの列名を変更する場合は、1 か所で更新できる文字列定数を使用できます (使用する必要があります)。
列名を介して列/行の値にアクセスすることは、人間が読むことと上位互換性(将来誰かが列の順序または数を変更した場合)に適しています。
列のインデックスを介して列/行の値にアクセスすると、パフォーマンスが向上します。
したがって、1つまたは2つの行の値を変更する場合は、列名に問題はありません。ただし、数千行の値を変更する場合は、列名から計算された列インデックスを使用する必要があります。
int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
record[ndxMyColumn] = 15;
}
他の人に完全に同意します。速度よりも読みやすさと保守性を重視してください。ただし、名前付き列をパラメーターとして渡す必要がある一般的なメソッドがあったため、列インデックスが何であるかを理解することは理にかなっています。
以下のベンチマークでは、列インデックスを使用すると大きな改善が見られたので、これがボトルネック領域またはコードのパフォーマンスの重要な部分である場合は、価値があるかもしれません.
以下のコードからの出力は次のとおりです。
ColumnIndex で 515 ミリ秒
ColumnName で 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;
}
列名が最善の方法だと思います。何をプルしているかを判断する方が簡単で、列の順序は select ステートメントによって決定されますが、これは後で変更される可能性があります。列名も変更される可能性があると主張することができますが、これは可能性がはるかに低いと思います.
編集:
実際、列インデックスの使用に本当に熱心な場合は、列インデックスの定数を作成し、その定数に列の名前を付けることができます。そう:
PRIMARY_KEY_COLUMN_NAME_INDEX = 0
それは少なくともそれを読みやすくするでしょう。
それはあなたが必要とするものに依存します。私の場合、DataSetの数千行に対して集中的な処理を実行しているときに速度が最優先される状況があったため、名前で列インデックスをキャッシュするコードを作成することにしました。次に、ループコードで、キャッシュされたインデックスを使用しました。これにより、列名を直接使用するよりもパフォーマンスが大幅に向上しました。
もちろん、マイレージは異なる場合があります。私の状況はかなり不自然で珍しいケースでしたが、その場合はかなりうまくいきました。
私の意見では、コードをプロファイリングし、それがボトルネックとして示された場合にのみ、インデックスに切り替える必要があります。これは起こらないと思います。
名前を付けるのは良いことです。私たちの限られた脳が問題を理解し、リンクを簡単に作成できるようにします。そのため、Human[189333847]、Human[138924342]、Human[239333546] ではなく、Fred、Martin、Jamie などの名前が付けられています。
名前を付けてください、あなたはより良いエラーメッセージを受け取ります:)
読みやすさと保守性のために、文字列を選択します。文字列定数を使用して、列名の値を定義します。元:
public class ExampleDataColumns
{
public const string ID = "example_id";
public const string Name = "example_name";
....
}
次に、次のように後で参照できます。
row[ExampleDataColumns.ID]
プログラマーが SQL で列インデックスを指定する必要があるため、RDBMS が高速化されないのと同じトークンで DataRow の列名を使用します。ただし、SELECT ステートメントを発行するときに RDBMS が動作する方法を模倣することもできます。RDBMS エンジン内では、行をトラバースする前に SELECT 句で指定された列の列インデックス/オフセットを照会するため、より高速に動作できます。
本当に速度を上げたい場合は、const/enum の方法で実行しないでください (データベースまたは ORM レイヤーで列の順序が変わる可能性があります)。TcKsが提案したように(実際のループの前に)実行してください:
int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
record[ndxMyColumn] = 15;
}
将来、列名を変更してデータベースを難読化することにした場合は、クエリでそれらの列にエイリアスを設定して、インデクサー コードの機能を維持することができます。名前で索引付けすることをお勧めします。
私の場合、テーブルからcolumnnameColumnを取得するために、リフレクションを使用しています(これが自分の名前の正しい方法かどうかはわかりません)。
「ハードコーディング」は優れていません
int price = (int)dr[DatableVar.PriceColumn];