.Net DataSetsで列名または列インデックスを使用する方が良いですか?
-
19-08-2019 - |
質問
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ステートメントによって決定されます。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]
DataRowの列名は、RDBMSがSQLで列インデックスを指定することをプログラマに要求することで速度が得られないのと同じトークンで使用します。ただし、おそらくSELECTステートメントを発行するときのRDBMSの動作を模倣することができます。RDBMSエンジン内で、行を走査する前にSELECT句で指定された列の列インデックス/列のクエリを行うため、より高速に動作できます。
本当に速度を上げたい場合は、[しない] const / enumの方法で実行します(データベースまたはORMレイヤーで列の順序が変わる場合があります)。 TcKが提案したとおりに実行します(実際のループの前に):
int ndxMyColumn = table.Columns.IndexOf( "MyColumn" );
foreach(DataRow record in table.Rows ) {
record[ndxMyColumn] = 15;
}
私のために、テーブルからcolumnnameColumnを取得するためにリフレクションを使用しています(自分が何をするのが正しい方法かわかりません)
no <!> quot; hardcoding <!> quot;より良い
int price = (int)dr[DatableVar.PriceColumn];