IDataReader を使うときそのままだとこんな感じだと思うんですが、
int intValue = (int) reader["int_field"]; string strValue = (string) reader["str_field"];
NULL のときとかちょっと面倒です。(なんで IDataReader.IsDBnull には IsDBNull(string name) みたいなオーバーロードがないんだろう
Nullable<int> nullableValue = null; if (!reader.IsDBNull(reader.GetOrdinal("nullable_field"))) { nullableValue = (int) reader["nullable_field"]; }
なのでこんな風にできるようにしたい。
int intValue = reader.Field<int>("int_field"); string strValue = reader.Field<string>("str_field"); Nullable<int> nullableValue = reader.Field<Nullable<int>>("nullable_field"); int ifNullValue = reader.Field<int>("if_null_field", ifNull:-1);
3.5以上なら拡張メソッド作ればいいんですが... 残念ながら 2.0 な環境だったのでこんなヘルパクラスを作って実装しました。
public class DataReaderHelper : IDataReader | |
{ | |
public DataReaderHelper(IDataReader reader) | |
{ | |
if (reader == null) throw new ArgumentNullException("reader"); | |
_reader = reader; | |
} | |
private readonly IDataReader _reader; | |
public T Field<T>(string fieldName) | |
{ | |
return Field<T>(_reader, fieldName, default(T), false); | |
} | |
public T Field<T>(string fieldName, T ifNull) | |
{ | |
return Field<T>(_reader, fieldName, ifNull, true); | |
} | |
public bool IsDBNull(string fieldName) | |
{ | |
return _reader.IsDBNull(_reader.GetOrdinal(fieldName)); | |
} | |
private static T Field<T>(IDataReader reader, string fieldName, T ifNull, bool useIfNull) | |
{ | |
Type type = typeof (T); | |
Type valueType = Nullable.GetUnderlyingType(type); | |
bool typeIsNullable = (valueType != null); | |
if (!typeIsNullable) | |
valueType = type; | |
if (Convert.IsDBNull(reader[fieldName])) | |
{ | |
if (typeIsNullable || !valueType.IsValueType || useIfNull) | |
return ifNull; | |
throw new InvalidCastException(); | |
} | |
return (T)reader[fieldName]; | |
} | |
public void Close() | |
{ | |
_reader.Close(); | |
} | |
public int Depth | |
{ | |
get { return _reader.Depth; } | |
} | |
public DataTable GetSchemaTable() | |
{ | |
return _reader.GetSchemaTable(); | |
} | |
public bool IsClosed | |
{ | |
get { return _reader.IsClosed; } | |
} | |
public bool NextResult() | |
{ | |
return _reader.NextResult(); | |
} | |
public bool Read() | |
{ | |
return _reader.Read(); | |
} | |
public int RecordsAffected | |
{ | |
get { return _reader.RecordsAffected; } | |
} | |
public void Dispose() | |
{ | |
_reader.Dispose(); | |
} | |
public int FieldCount | |
{ | |
get { return _reader.FieldCount; } | |
} | |
public bool GetBoolean(int i) | |
{ | |
return _reader.GetBoolean(i); | |
} | |
public byte GetByte(int i) | |
{ | |
return _reader.GetByte(i); | |
} | |
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) | |
{ | |
return _reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length); | |
} | |
public char GetChar(int i) | |
{ | |
return _reader.GetChar(i); | |
} | |
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) | |
{ | |
return _reader.GetChars(i, fieldoffset, buffer, bufferoffset, length); | |
} | |
public IDataReader GetData(int i) | |
{ | |
return _reader.GetData(i); | |
} | |
public string GetDataTypeName(int i) | |
{ | |
return _reader.GetDataTypeName(i); | |
} | |
public DateTime GetDateTime(int i) | |
{ | |
return _reader.GetDateTime(i); | |
} | |
public decimal GetDecimal(int i) | |
{ | |
return _reader.GetDecimal(i); | |
} | |
public double GetDouble(int i) | |
{ | |
return _reader.GetDouble(i); | |
} | |
public Type GetFieldType(int i) | |
{ | |
return _reader.GetFieldType(i); | |
} | |
public float GetFloat(int i) | |
{ | |
return _reader.GetFloat(i); | |
} | |
public Guid GetGuid(int i) | |
{ | |
return _reader.GetGuid(i); | |
} | |
public short GetInt16(int i) | |
{ | |
return _reader.GetInt16(i); | |
} | |
public int GetInt32(int i) | |
{ | |
return _reader.GetInt32(i); | |
} | |
public long GetInt64(int i) | |
{ | |
return _reader.GetInt64(i); | |
} | |
public string GetName(int i) | |
{ | |
return _reader.GetName(i); | |
} | |
public int GetOrdinal(string name) | |
{ | |
return _reader.GetOrdinal(name); | |
} | |
public string GetString(int i) | |
{ | |
return _reader.GetString(i); | |
} | |
public object GetValue(int i) | |
{ | |
return _reader.GetValue(i); | |
} | |
public int GetValues(object[] values) | |
{ | |
return _reader.GetValues(values); | |
} | |
public bool IsDBNull(int i) | |
{ | |
return _reader.IsDBNull(i); | |
} | |
public object this[string name] | |
{ | |
get { return _reader[name]; } | |
} | |
public object this[int i] | |
{ | |
get { return _reader[i]; } | |
} | |
} |
DataReaderHelper reader = new DataReaderHelper(command.ExecuteReader()); | |
while (reader.Read()) | |
{ | |
int intValue = reader.Field<int>("int_field"); | |
string strValue = reader.Field<string>("str_field"); | |
Nullable<int> nullableValue = reader.Field<Nullable<int>>("nullable_field"); | |
int ifNullValue = reader.Field<int>("if_null_field", ifNull:-1); | |
} |
まあ実際は VB.NET なんですが... これで IDataReader が少し使いやすくなりました。