1

我正在使用 Visual Studios 2010 创建带有数据库的 ac# Web 应用程序。我的目标是让 default.aspx 调用 ac# 类,该类运行一个存储过程,从表中选择一个条目并返回它。这是代码:

'The stored procedure.  I want it to send back the name it gets from doing
'the query to the c# class.
ALTER PROCEDURE getName (@id int)
AS
BEGIN
SET NOCOUNT ON;

--   
SELECT name FROM tableA where id = @id;

END 
Return
//Here's the c# class I'm using.
public class student
{
    public string name;
    public int id;

    public student()
    { }

    public String doQuery(int id)
    {
        SqlConnection conn = null;

        try
        {
             conn = new SqlConnection("Server =(local); Database = Database1.mdf;
   Integrated Security = SSPI");
            conn.Open();
            SqlCommand cmd = new SqlCommand("getName", conn);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlParameter param = new SqlParameter("@id", SqlDbType.Int);
            param.Direction = ParameterDirection.Input;
            param.Value = id;
            cmd.Parameters.Add(param);
            //This is some code from when I tryed return value
            //SqlParameter reVal = cmd.Parameters.Add("@name", SqlDbType.VarChar);
            //reVal.Direction = ParameterDirection.ReturnValue;

            //before using ExecuteScalar I tried ExcuteNonQuery with the commented    
            //out code
            name = (string)cmd.ExecuteScalar();

            //name = (String)cmd.Parameters["@name"].Value;

            conn.Close();
        }

        catch(Exception)
        {}
        return name;
    }
}

运行我的程序不会返回错误,它根本不会在名称中放置任何值。我缺少什么将 sql 过程中选择的名称放入我的 c# 类中的 name 变量中。我希望我能清楚地表达我的问题。

编辑1:我没有在catch中放任何东西,因为还没有决定用什么来查看它是否出错。当尝试失败时,我将其更改为 make name = "error",这就是我得到的,这就是我得到的。我还尝试在 sql server 管理中运行“exec getName 5, others”。我有点不清楚在运行 exec getName 时使用什么作为第二个参数,因为第二个参数假设只是输出,但似乎仍然需要运行它。它只是说命令执行成功,但不显示 id 5 的名称

4

2 回答 2

2

问题出在您的连接字符串中:除非您有奇怪的命名约定,否则您指定的是数据库文件名而不是数据库本身的名称。

尝试将这部分连接字符串:Database = Database1.mdf;更改为Database = Database1;.

如果您对连接字符串中的有效或无效内容感到困惑,您始终可以使用SqlConnectionStringBuilder,它会在您设置正确的属性后为您创建适当的连接字符串。

您还可以使用SqlConnection.ConnectionString文档中指定的属性列表作为包含示例的参考。

最后,我强烈推荐以下最佳实践:

1) 使用带有连接和命令的块来确保它们被正确关闭和处理。

2) 不要将名称直接分配给 ExecuteScalar 的结果,以防它返回为 DBNull.Value

3) 永远不要忽略异常,除非您在代码中记录了这样做的原因。

以下是所有上述建议的快速重写:

        try
        {
            using (var conn = new SqlConnection("Server =(local); Database = Database1; Integrated Security = SSPI"))
            {
                conn.Open();
                using (var cmd = new SqlCommand("getName", conn))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    var param = new SqlParameter("@id", SqlDbType.Int);
                    param.Direction = ParameterDirection.Input;
                    param.Value = id;
                    cmd.Parameters.Add(param);

                    var oResult = cmd.ExecuteScalar();
                    if ((oResult != null) && (oResult != DBNull.Value))
                    {
                        name = (string)oResult;
                    }
                }
                conn.Close();
            }
        }

        catch (Exception)
        { 
            //  Do something with the exception here, don't just ignore it
        }
于 2013-01-14T01:30:24.997 回答
2

我建议对SQL语句使用async/await模式。幸运的是,它不需要太多重构。

看看这是否适合你:

public async Task<string> QueryGetNameAsync(int id)
{
  using (var dbConn = new SqlConnection("..."))
  using (var command = new SqlCommand("getName", dbConn))
  {
    try
    {
      command.CommandType = CommandType.StoredProcedure;
      command.Parameters.AddWithValue("@id", id);

      await dbConn.OpenAsync();

      var result = await command.ExecuteScalarAsync();
      dbConn.Close();

      var name = result as string;          
      return name;
    }
    catch (Exception ex)
    {
      // Handle exception here.
    }
  }
}

你可以这样称呼它:

private async void DoLookup_Clicked(object sender, EventArgs e)
{
   var id = int.Parse(idText.Text);
   var name = await QueryGetNameAsync(id);
}

或者,可以在SQLOUTPUT中使用参数,但您必须将存储过程调整为如下所示:

ALTER PROCEDURE getName
(
  @id int, 
  @name varchar(100) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON;

SELECT @name = name FROM tableA where id = @id;

END 

那么您的C#函数将类似于:

public async Task<string> QueryGetNameAsync(int id)
{
  using (var dbConn = new SqlConnection("..."))
  using (var command = new SqlCommand("getName", dbConn))
  {
    try
    {
      command.CommandType = CommandType.StoredProcedure;
      command.Parameters.AddWithValue("@id", id);
      command.Parameters.Add("@name", SqlDbType.VarChar, 100);
      command.Parameters["@name"].Direction = ParameterDirection.Output;

      await dbConn.OpenAsync();
      await command.ExecuteNonQueryAsync();
      dbConn.Close();

      var name = command.Parameters["@name"].Value as string;          
      return name;
    }
    catch (Exception ex)
    {
      // Handle exception here.
    }
  }
}
于 2013-01-14T00:13:39.673 回答