0

クエリを実行し、次のようなスカラー値を返す関数があります。

        public T GetScalarValue<T>(string sql)
        {
            T t;
            try {
                SqlConnection conn = new SqlConnection("MY_SQL_SERVER_CONNECTION_STRING");
                conn.Open();
                SqlCommand cmd = new SqlCommand(sql, conn);
                t = (T)cmd.ExecuteScalar();
            }
            catch (Exception ex) {
                throw ex;
            }
            finally{
                if(conn.State == ConnectionState.Open)
                    conn.Close();
            }
            return t;
        }

指定された SQL でこの関数を呼び出すと、結果が得られます。

int result = dal.GetScalarValue<int>("SELECT [schema_id] FROM SYS.SCHEMAS WHERE [name] = 'dbo'")

クエリは int 値を返すため、これは正常に機能しますが、何も返さないクエリに対して同じものを呼び出すと、関数は失敗します。

int result = dal.GetScalarValue<int>("SELECT [schema_id] FROM SYS.SCHEMAS WHERE [name] = 'Foooo'")

cmd.ExecuteScalar() は結果を返さないため、「オブジェクト参照がオブジェクトのインスタンスに設定されていません」という例外が発生します。しかし、私はこの関数が与えられたタイプのデフォルト値を返すことを望んでいます (例: int の場合は 0、decimal-0.00、string の場合は空の値、datetime の場合は '1900-01-01' など)。

これに対するより良い解決策を見つけたら、私に知らせてください。

助けてくれてありがとう。

4

2 に答える 2

2

コードを少しリファクタリングして、読みやすくします。

public T GetScalarValue<T>(string sql) where T : struct
{
    string connectionString = "MY_SQL_SERVER_CONNECTION_STRING";

    using (var connection = new SqlConnection(connectionString))
    using (var command = new SqlCommand(sql, connection))
    {
        connection.Open();
        var obj = command.ExecuteScalar();

        return (obj != null) ? (T)obj : default(T);
    }
}
于 2012-10-04T15:47:48.130 に答える
1

次のようなことを試してください:

public T GetScalarValue<T>(string sql)
{
    T result = default(T);

    try
    {
        using (SqlConnection conn = new SqlConnection("MY_SQL_SERVER_CONNECTION_STRING"))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            conn.Open();

            var scalar = cmd.ExecuteScalar();

            if (scalar != null)
            {
                result = (T)Convert.ChangeType(scalar, typeof(T));

                // or result = (T)scalar    if that works better for you.
            }
        }

        return result;
    }
    catch (Exception ex)
    {
        // Log the exception maybe?
        return result;
    }
}

ここでresultは、 type のデフォルト値になるように設定していますT。次に、例外があれば、そこに戻りresultます。したがって、失敗した例では、値 0 が返されます。

編集:

コメントで良い点が提起されました。私があなたに与えた例外ハンドラでは、result. 何か問題が発生したかどうかがわかるように、例外をログに記録するか、何らかの形で記録することをお勧めします。NLog1 つのアイデアは、たとえばorのようなロガーを使用して例外をログに記録することLog4Netです。選択肢はたくさんあります。

于 2012-10-04T14:55:31.357 に答える