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、十进制 - 0.00,对于字符串 - 一个空值,对于 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. 最好记录或以某种方式记录异常,以便您知道是否出了问题。一个想法是使用诸如NLog或之类的记录器来记录异常Log4Net- 有很多选择。

于 2012-10-04T14:55:31.357 回答