お知らせ
          
        2019年7月12日
C#ネタ その② SqlDataReaderで返却される実行結果をDTOへ変換する
C#は様々なライブラリが用意されており、NuGetを使い簡単に導入でき、データベースまわりは1から作ると大変なので、
EntityFrameworkを用いて開発を行っていました。
しかし、80カラムほどあるデータで件数が1万件を超えたあたりからとんでもなくパフォーマンスが落ちます。
Stopwatchを仕込み、ボトルネックを調べた所、実行結果⇒Dtoに変換するあたりが遅いと判明しました。
せっかくトランザクション制御をあまり意識せず使えるEntityFrameworkですが、開発も終盤で今更変更できないので、
この変換部分だけ別途作りました。
前回投稿したネタ①と似たようなお話になります。
public List<T> ConvertDto<T>(SqlCommand command)
{
    List<T> dtoList = new List<T>();
    // SQLを実行
    // usingブロックが終わり次第、コネクションを閉じるようにCommandBehavior.CloseConnectionを指定
    using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
    {
        // 行データ分のループ
        while (reader.Read())
        {
            // Tで指定された総称型のインスタンスを生成(DTOの作成)
            T dtoObject = (T)Activator.CreateInstance(typeof(T));
            
            foreach (PropertyInfo property in dtoObject.GetType().GetProperties())
            {
                if (!DBNull.Value.Equals(reader[property.Name]))
                {
                    // プロパティ(フィールド)名を元に、SqlDataReaderから値を取得し、DTOにセット
                    property.SetValue(dtoObject, reader[property.Name], null);
                }
            }
            dtoList.Add(dtoObject);
        }
    }
    return dtoList;
}
記載はしていませんが、EntityFrameworkと一緒に使うので、SqlCommandに設定するコネクションはEntityFrameworkのContextから取得します。
今後、似たような場面ですぐ利用できるように個人的なメモとして記載しておきます。