2012年10月20日土曜日

[C#]IDataReader をちょっと使いやすくする

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);
}
view raw UseCase.cs hosted with ❤ by GitHub

まあ実際は VB.NET なんですが... これで IDataReader が少し使いやすくなりました。

0 件のコメント:

コメントを投稿

Factorio: Space Exploration クリア記録

 工場建設クラフトゲーム、Factorio の MOD である Space Exploration のクリア記録です。 はじめに プレイ時間は約 350 時間、2023年10月から2025年2月にかけて15ヶ月間に及びました。この期間中3人の友人と毎週末、工場勤務に明け暮れました...