0

我正在为 c# 中的 sql 进行选择查询。尝试使用SqlParameter,但是当我调试时,我抛出了一个异常:

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

我通过文本框将值传递给类中的属性Customer。这是我的事件处理程序中的内容:

var newCustomer = new Customer();
newCustomer.FirstName = textBoxFirstName.Text;
newCustomer.LastName = textBoxLastName.Text;
newCustomer.Address = textBoxAddress.Text;
newCustomer.City = textBoxCity.Text;
newCustomer.State = textBoxState.Text;
newCustomer.Zip = Int32.Parse(textBoxZip.Text);
newCustomer.Phone = Int64.Parse(textBoxPhone1.Text);
newCustomer.Notes = textBoxNotes.Text;

var crochetDataHandler = new CrochetDataHandler();
crochetDataHandler.InsertNewCustomer(newCustomer);

这是我正在调用的方法:

public void InsertNewCustomer(Customer customer)
{
        var insertCustomerString = 
"Insert into Customer1 (FirstName, LastName, Address, City, State, Zip, Phone, Notes) Values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)";

    SqlCommand newCust = new SqlCommand(insertCustomerString);
    newCust.Parameters.Add(new SqlParameter("@p1", customer.FirstName));
    newCust.Parameters.Add(new SqlParameter("@p2", customer.LastName));
    newCust.Parameters.Add(new SqlParameter("@p3", customer.Address));
    newCust.Parameters.Add(new SqlParameter("@p4", customer.City));
    newCust.Parameters.Add(new SqlParameter("@p5", customer.State));
    newCust.Parameters.Add(new SqlParameter("@p6", customer.Zip));
    newCust.Parameters.Add(new SqlParameter("@p7", customer.Phone));
    newCust.Parameters.Add(new SqlParameter("@p8", customer.Notes));

    newCust.CommandText.ToString();
    InsertRecord(insertCustomerString);

我在其他问题中看到了一些不同的构造函数SqlParameter,但是当我尝试它们时,我得到了同样的异常。

4

2 回答 2

4

我不确定您的 InsertRecord 方法在做什么,但是您将原始字符串 insertCustomerString 传递给它,而不是您的 SqlCommand 对象。字符串对您对参数所做的操作一无所知,因此如果 InsertRecord 期望字符串知道参数的值,它会感到失望。

于 2013-05-18T21:02:27.827 回答
0

下面是如何做到这一点。
此外,您永远不应该使用原始 System.Data.SqlClient 对象,而应该使用通用接口类型。

 System.Data.IDbConnection idbc = new System.Data.SqlClient.SqlConnection("connectionstring");
    System.Data.IDbCommand cmd = idbc.CreateCommand();
    cmd.CommandText = "INSERT INTO Customer1 (FirstName, LastName, Address, City, State, Zip, Phone, Notes) Values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)";
    System.Data.IDbDataParameter parm = cmd.CreateParameter();
    parm.DbType = System.Data.DbType.AnsiString;
    parm.ParameterName = "@p1";
    parm.Value = "ValueOfP1";
    cmd.Parameters.Add(parm);
    // etc.

    if(cmd.Connection.State != System.Data.ConnectionState.Open)
        cmd.Connection.Open();
    cmd.ExecuteNonQuery();

    if (cmd.Connection.State != System.Data.ConnectionState.Closed)
        cmd.Connection.Close();

此外,您应该使用并锁定所有有价值的对象;)

    using (System.Data.IDbConnection idbc = new System.Data.SqlClient.SqlConnection("connectionstring"))
    {

        lock (idbc)
        {

            using (System.Data.IDbCommand cmd = idbc.CreateCommand())
            {
                lock (cmd)
                {

                    cmd.CommandText = "INSERT INTO Customer1 (FirstName, LastName, Address, City, State, Zip, Phone, Notes) Values (@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8)";
                    System.Data.IDbDataParameter parm = cmd.CreateParameter();
                    parm.DbType = System.Data.DbType.AnsiString;
                    parm.ParameterName = "@p1";
                    parm.Value = "ValueOfP1";
                    cmd.Parameters.Add(parm);

                    //

                    if (cmd.Connection.State != System.Data.ConnectionState.Open)
                        cmd.Connection.Open();
                    cmd.ExecuteNonQuery();

                    if (cmd.Connection.State != System.Data.ConnectionState.Closed)
                        cmd.Connection.Close();
                }
            }
        }
    }

作为奖励,您不应使用新的 System.Data.SqlClient.SqlConnection,而应使用工厂类型,例如:

System.Data.Common.DbProviderFactory fac = System.Data.Common.DbProviderFactories.GetFactory("System.Data.SqlClient");

            System.Data.IDbConnection idbc = fac.CreateConnection();
            idbc.ConnectionString = "ConnectionString";

此外,您可以自动将您的值映射到相应的 sql 类型:

// From Type to DBType
protected virtual System.Data.DbType GetDbType(Type type)
{
    // http://social.msdn.microsoft.com/Forums/en/winforms/thread/c6f3ab91-2198-402a-9a18-66ce442333a6
    string strTypeName = type.Name;
    System.Data.DbType DBtype = System.Data.DbType.String; // default value

    try
    {
        if (object.ReferenceEquals(type, typeof(System.DBNull)))
        {
            return DBtype;
        }

        if (object.ReferenceEquals(type, typeof(System.Byte[])))
        {
            return System.Data.DbType.Binary;
        }

        DBtype = (System.Data.DbType)Enum.Parse(typeof(System.Data.DbType), strTypeName, true);

        // Es ist keine Zuordnung von DbType UInt64 zu einem bekannten SqlDbType vorhanden.
        // http://msdn.microsoft.com/en-us/library/bbw6zyha(v=vs.71).aspx
        if (DBtype == System.Data.DbType.UInt64)
            DBtype = System.Data.DbType.Int64;
    }
    catch (Exception)
    {
        // add error handling to suit your taste
    }

    return DBtype;
} // End Function GetDbType


public virtual System.Data.IDbDataParameter AddParameter(System.Data.IDbCommand command, string strParameterName, object objValue)
{
    return AddParameter(command, strParameterName, objValue, System.Data.ParameterDirection.Input);
} // End Function AddParameter


public virtual System.Data.IDbDataParameter AddParameter(System.Data.IDbCommand command, string strParameterName, object objValue, System.Data.ParameterDirection pad)
{
    if (objValue == null)
    {
        //throw new ArgumentNullException("objValue");
        objValue = System.DBNull.Value;
    } // End if (objValue == null)

    System.Type tDataType = objValue.GetType();
    System.Data.DbType dbType = GetDbType(tDataType);

    return AddParameter(command, strParameterName, objValue, pad, dbType);
} // End Function AddParameter


public virtual System.Data.IDbDataParameter AddParameter(System.Data.IDbCommand command, string strParameterName, object objValue, System.Data.ParameterDirection pad, System.Data.DbType dbType)
{
    System.Data.IDbDataParameter parameter = command.CreateParameter();

    if (!strParameterName.StartsWith("@"))
    {
        strParameterName = "@" + strParameterName;
    } // End if (!strParameterName.StartsWith("@"))

    parameter.ParameterName = strParameterName;
    parameter.DbType = dbType;
    parameter.Direction = pad;

    // Es ist keine Zuordnung von DbType UInt64 zu einem bekannten SqlDbType vorhanden.
    // No association  DbType UInt64 to a known SqlDbType

    if (objValue == null)
        parameter.Value = System.DBNull.Value;
    else
        parameter.Value = objValue;

    command.Parameters.Add(parameter);
    return parameter;
} // End Function AddParameter


public virtual T GetParameterValue<T>(System.Data.IDbCommand idbc, string strParameterName)
{
    if (!strParameterName.StartsWith("@"))
    {
        strParameterName = "@" + strParameterName;
    }

    return InlineTypeAssignHelper<T>(((System.Data.IDbDataParameter)idbc.Parameters[strParameterName]).Value);
} // End Function GetParameterValue<T>

如果你这样做,你可以保持与所有 ado.net 数据库提供程序的可移植性,并且只需要在更改数据库类型时调整 getfactory 中的字符串以及你的 sql 代码。

如果您按照自己的方式进行操作,则首先必须大幅更改您的代码,然后才能更改 sql。

于 2013-05-18T21:17:52.363 回答