从存储过程获取数据作为数据表

时间:2018-07-11 21:36:11

标签: c# sql-server winforms

我有一种使用存储过程作为DataTable从数据库中检索数据的方法,例如:

public DataTable GetTableBySQL(string sql) 
{
    SqlCommand cmd = new SqlCommand(sql.ToString(), this.dbconn) 
    {
        CommandTimeout = 0,
        CommandType = CommandType.Text
    };

    DataTable tbl = new DataTable("Table1") 
    {
        Locale = System.Globalization.CultureInfo.InvariantCulture
    };

    SqlDataAdapter da = new SqlDataAdapter(cmd);

    try 
    {
        da.SelectCommand.CommandTimeout = 0;
        da.Fill(tbl);
    } 
    catch (SqlException e) 
    {
        this.HandleSQLError(e, "GetTableBySQL", sql.ToString());
    }
    finally
    {
        cmd.Dispose();
        da.Dispose();
    }

    return tbl;
}

现在我这样调用存储过程:

var empList = db.GetTableBySQL("$exec getMySP");

但是当我执行时,它只是不返回任何列。

我在做什么错?问候

1 个答案:

答案 0 :(得分:1)

这里存在三个主要问题(其他较小的问题,但三个很重要):

  1. SQL的$exec部分没有任何意义。也许您只想要exec
  2. 当错误的SQL失败时,该错误将隐藏在程序中,因此您真的不知道发生了什么。
  3. 方法签名不支持查询参数,因此将迫使您编写可怕的不安全代码,导致 会导致有人入侵您的应用程序。大概早点而不是迟点。 确实很糟糕,您不应忽略它。

尝试更多类似的方法:

public DataTable GetTableBySQL(string sql, params SqlParameter[] parameters) 
{
    var result = new DataTable();

    //ADO.Net really does work better when you create a **NEW** connection
    //  object for most queries. Just share the connection string.
    //Also: "using" blocks are a better way to make sure the connection is closed.
    using (var dbconn = new SqlConnection(this.dbConnectionString))
    using (var cmd = new SqlCommand(sql, dbconn))
    using (var da = new SqlDataAdapter(cmd))
    {
        cmd.CommandTimeout = 0;
        // A number of the properties set on the cmd and tbl variables just set the same value that was already there, didn't accomplish anything

        //It's hard to understate how important it is to use parameterized queries.
        if (parameters != null && parameters.Length > 0)
        {
            cmd.Parameters.AddRange(parameters);
        }

        try
        {
            da.Fill(result);
        } 
        catch (SqlException e) 
        {
            this.HandleSQLError(e, "GetTableBySQL", sql.ToString());
            //you may want to re-throw here, 
            // or even just remove the try/catch and let the error bubble up to calling code
        }
    }  
    return result;
}

这里还是没有所有多余的解释性注释,因此您可以看到正确执行代码是 less 代码,而不是更多代码:

public DataTable GetTableBySQL(string sql, params SqlParameter[] parameters) 
{
    var result = new DataTable();

    using (var dbconn = new SqlConnection(this.dbConnectionString))
    using (var cmd = new SqlCommand(sql, dbconn))
    using (var da = new SqlDataAdapter(cmd))
    {
        cmd.CommandTimeout = 0;
        if (parameters != null && parameters.Length > 0)
        {
            cmd.Parameters.AddRange(parameters);
        }

        da.Fill(result);
    }  
    return result;
}

然后这样称呼它:

var empList = db.GetTableBySQL("exec getMySP");