7

私は現在、このメソッドを使用してDataReaderからデータを読み取ります-

private T GetValue<T>(object obj)
{
    if (typeof(DBNull) != obj.GetType())
    {
        return (T)obj;
    }
    return default(T);
}

上記のメソッドを-として呼び出す

GetValue<int>(dataReader["columnName1"])
GetValue<string>(dataReader["columnName2"])
GetValue<float>(dataReader["columnName3"])

ただし、エラーcolumnName3のように値がある場合、これは失敗します7200000
Invalid Cast Exception.

私は自分のメソッドを変更して置き換えることを考えています-

return (T)obj;

return (T)Convert.ChangeType(obj, typeof(T));

しかし、この変更には2回の型キャストが含まれるため、より良い方法を楽しみにしています。
より良いアイデアはありますか?

ありがとうございました!

4

2 に答える 2

4

ジェネリック メソッドには、多くのコードの肥大化を減らすことができるという利点がありますが、それ以外の場合は、データ型ごとに独自のラッパーを作成することで、カスタム処理を柔軟に行うことができます。そしておそらく、データベースクエリは、検索モードよりもパフォーマンスに顕著な影響を与えるでしょう.

1 つの一般的なアプローチよりも、独自の拡張メソッドのセットを作成することをお勧めします。メソッドを拡張するIDataReaderと、オブジェクトのサブタイプ全体にメソッドを伝播しないという利点があります。さまざまなコネクタが特にGuidタイプによって異なる動作をするため、タイプを個別に処理する必要がありました。また、 datareader が値を読み取ったかどうか、0または両方のケースでDBNullいつ戻ってきたかを知るのは困難です。0テーブルに null 値を持つ enum フィールドがあるとします。最初の列挙型として読み取られるようにしたいのはなぜですか?

ただ電話してください:

dataReader.GetInt("columnName1")
dataReader.GetString("columnName3")
dataReader.GetFloat("columnName3")

そしてメソッド:

public static int? GetInt(this IDataReader r, string columnName)
{
    var i = r[columnName];      
    if (i.IsNull())
        return null; //or your preferred value

    return (int)i;
}

public static bool IsNull<T>(this T obj) where T : class
{
    return (object)obj == null || obj == DBNull.Value;
}

同様に、

public static string GetString(this IDataReader r, string columnName)
{
}

public static float GetFloat(this IDataReader r, string columnName)
{
}

本当に 1 つの汎用関数が必要な場合は、それも使用できます。

public static T Get<T>(this IDataReader r, string columnName, T defaultValue = default(T))
{
    var obj = r[columnName];      
    if (obj.IsNull())
        return defaultValue;

    return (T)obj;
}

だから呼んで

dataReader.Get<int>(1); //if DBNull should be treated as 0
dataReader.Get<int?>(1); //if DBNull should be treated as null
dataReader.Get<int>(1, -1); //if DBNull should be treated as a custom value, say -1

つまり、コメントで指摘されているように、正しいタイプでキャストしていないため、エラーが発生します。組み込みのチェックを使用することもできましたが、マイクロ最適化のこの奇妙なケースから着想を得てDBNull、リーダーからデータが複数回読み取られることを避けたくありません。

于 2013-02-02T22:36:50.793 に答える
1

.NET Framework 4.5 以降

static class SqlReaderExtension
{
    public static async Task<T> ReadAsync<T>(this SqlDataReader reader, string fieldName)
    {
        if (reader == null) throw new ArgumentNullException(nameof(reader));
        if (string.IsNullOrEmpty(fieldName))
            throw new ArgumentException("Value cannot be null or empty.", nameof(fieldName));

        int idx = reader.GetOrdinal(fieldName);
        return await reader.GetFieldValueAsync<T>(idx);
    }
}

その後

string result = await reader.ReadAsync<string>("FieldName");
于 2016-07-12T08:44:54.703 に答える