【问题标题】:SqlException was unhandled, C# [closed]SqlException 未处理,C# [关闭]
【发布时间】:2021-10-23 08:52:07
【问题描述】:

我应该如何处理这个错误?我在selectall 方法中使用了这段代码,一切都很好,但是在selectrow 中我得到了这个错误。

代码:

public DataTable SelectRow(string ContactID)
{
    string query = "Select * from ContactsList Where ContactID = @ID";

    SqlConnection connection = new SqlConnection(ConnectionString);

    SqlDataAdapter adapter = new SqlDataAdapter(query, connection);

    DataTable data = new DataTable();
    adapter.Fill(data);

    return data;
}

错误:

System.Data.dll 中出现“System.Data.SqlClient.SqlException”类型的未处理异常

附加信息:

必须声明标量变量“@ID”。

【问题讨论】:

标签: c# sql sql-server ado.net sqlparameter


【解决方案1】:

以下代码

  • 应按照@Olivier Rogier 的建议创建参数作为参数。
  • 不使用 DataAdapter,将其视为本地 var 表明这一点。请改用命令对象。
  • 请注意,如果没有错误,则返回类型带有 DataTable,而如果引发运行时异常,则将 Exception 传递回调用者。
  • 建议不要使用 SELECT *(不是问题的一部分,但最好只问需要的,不要再问了)。

代码

public class DataOperations
{
    private static string connection = "Data Source=.\\sqlexpress;Initial Catalog=NorthWind2020;Integrated Security=True";

    public static (DataTable table, Exception exception) SelectRow(string contactId)
    {
        DataTable table = new DataTable();

        try
        {
            using (var cn = new SqlConnection { ConnectionString = connection })
            {
                using (var cmd = new SqlCommand { Connection = cn })
                {
                    cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = @contactId;";
                    cmd.Parameters.Add("@contactId", SqlDbType.NVarChar).Value = contactId;
                    cn.Open();
                    table.Load(cmd.ExecuteReader());
                    return (table, null);
                }
            }
        }
        catch (Exception exception)
        {
            return (null, exception);
        }

    }
}

上面调用方法的示例代码。

var (dataTable, exception) = DataOperations.SelectRow(contactIdentifier);
if (exception == null)
{
    Debug.WriteLine("Use table");
}
else
{
    Debug.WriteLine(exception.Message);
}

此外,如果联系人标识符指向单个记录,您可以简单地传回单个 DataRow 而不是整个 DataTable 或使用类的单个实例,例如

public class Contact
{
    // seems this would be an int
    public string ContactId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public override string ToString() => $"{FirstName} {LastName}";

}

获取数据的代码

public static Contact SelectContact(string contactId)
{

    Contact contact = new Contact() {ContactId = contactId};
    
    using (var cn = new SqlConnection { ConnectionString = connection })
    {
        using (var cmd = new SqlCommand { Connection = cn  })
        {
            cmd.CommandText = "SELECT FirstName, LastName FROM dbo.Contacts WHERE ContactId = @contactId;";
            cmd.Parameters.Add("@contactId", SqlDbType.NVarChar).Value = contactId;
            cn.Open();

            var reader = cmd.ExecuteReader();
            
            if (reader.HasRows)
            {
                reader.Read();
                contact.FirstName = reader.GetString(0);
                contact.LastName = reader.GetString(1);
            }

        }
    }

    return contact;
}

【讨论】:

    【解决方案2】:

    将标量变量传递给 SQL 原始查询(必须声明标量变量)

    您已声明参数@ID,但未传递参数的值。 我已将您的代码修改如下。

    public DataTable SelectRow(string ContactID)
    {
        SqlConnection connection = new SqlConnection(ConnectionString);
        string query = "Select * from ContactsList Where ContactID = @ID";
        SqlCommand cmd=new SqlCommand(query,connection);
        cmd.CommandType=CommandType.Text;
        cmd.Parameters.AddWithValue("@ID",ContactID);               
        SqlDataAdapter adapter = new SqlDataAdapter(cmd);
        DataTable data = new DataTable();
        adapter.Fill(data);
        return data;
    }
    

    您可以将 SqlCommand 对象“cmd”传递给 SqlDataAdapter 构造函数,该构造函数将根据指定的查询将数据加载到“适配器”对象。 希望以上代码对您有所帮助。

    【讨论】:

    • 虽然最好的做法是not use AddWithValue
    • 最佳实践也是用using处理连接、命令和适配器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多