1

单击 vb 中的添加按钮后,如果您不将文本框字段留空或为空,则它可以正常工作,代码执行良好

但是当将某些字段留空时,它会返回错误

无法将参数值从 String 转换为 Int32

存储过程

CREATE PROCEDURE AddOfficeEquipmentProfile
(
@OE_ID      varchar(11),    
@OE_Category        char(3) =NULL,      
@OE_SubCategory char(3)=    NULL,       
@OE_Name        varchar(35)=NULL,       
@OE_User        varchar(35)=NULL,   
@OE_Brand       varchar(15)=NULL,   
@OE_Model       varchar(35)=NULL,   
@OE_Specs       varchar(1000)=NULL,     
@OE_SerialNo        varchar(35)=NULL,   
@OE_PropertyNo  varchar(35)=NULL,   
@OE_MacAddress  varchar(100)=NULL,      
@OE_Static_IP       varchar(15)=NULL,   
@OE_Vendor      varchar(35)=NULL,   
@OE_PurchaseDate    smalldatetime,      
@OE_WarrantyInclusiveYear   int=NULL,   
@OE_WarrantyStatus  char(2)=    NULL,   
@OE_Status      varchar(15)=NULL,       
@OE_Dept_Code   char(3)=    NULL,   
@OE_Location_Code   char(8)=    NULL,       
@OE_Remarks     varchar(1000)=  NULL
)
AS

INSERT INTO tblOfficeEquipmentProfile (OE_ID, OE_Category, OE_SubCategory, OE_Name, OE_User, OE_Brand, OE_Model, OE_Specs, OE_SerialNo,
OE_PropertyNo, OE_MacAddress, OE_Static_IP, OE_Vendor, OE_PurchaseDate, OE_WarrantyInclusiveYear, OE_WarrantyStatus, OE_Status, OE_Dept_Code,
OE_Location_Code, OE_Remarks ) 
VALUES (@OE_ID, @OE_Category, @OE_SubCategory, @OE_Name, @OE_User, @OE_Brand, @OE_Model, 
@OE_Specs, @OE_SerialNo, @OE_PropertyNo, @OE_MacAddress, @OE_Static_IP, @OE_Vendor, @OE_PurchaseDate, @OE_WarrantyInclusiveYear, @OE_WarrantyStatus,
@OE_Status, @OE_Dept_Code, @OE_Location_Code, @OE_Remarks)

GO

VB.NET 代码

        cmd.CommandType = CommandType.StoredProcedure
        cmd.CommandText = "AddOfficeEquipmentProfile"

    cmd.Parameters.Add("@OE_ID", SqlDbType.VarChar, 11, "oeq-su-999")
    cmd.Parameters.Add("@OE_Category", SqlDbType.Char, 3, "COM").Value = DBNull.Value
    cmd.Parameters.Add("@OE_SubCategory", SqlDbType.Char, 3, "SU").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Name", SqlDbType.VarChar, 35, "adminpmis01").Value = DBNull.Value
    cmd.Parameters.Add("@OE_User", SqlDbType.VarChar, 35, "Ivan").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Brand", SqlDbType.VarChar, 15, "DELL").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Model", SqlDbType.VarChar, 35, "optiplex").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Specs", SqlDbType.VarChar, 1000, "dualcore").Value = DBNull.Value
    cmd.Parameters.Add("@OE_SerialNo", SqlDbType.VarChar, 35, "sgh5960").Value = DBNull.Value
    cmd.Parameters.Add("@OE_PropertyNo", SqlDbType.VarChar, 35, "j7h7h6g6f2").Value = DBNull.Value
    cmd.Parameters.Add("@OE_MacAddress", SqlDbType.VarChar, 100, "j7h7:h6g6f2").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Static_IP", SqlDbType.VarChar, 15, "192.168.1.5").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Vendor", SqlDbType.VarChar, 35, "ADWAYS").Value = DBNull.Value
    cmd.Parameters.Add("@OE_PurchaseDate", SqlDbType.DateTime)
    cmd.Parameters.Add("@OE_WarrantyInclusiveYear", SqlDbType.Int).Value = DBNull.Value
    cmd.Parameters.Add("@OE_WarrantyStatus", SqlDbType.Char, 2, "IN").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Status", SqlDbType.VarChar, 15, "Good").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Dept_Code", SqlDbType.Char, 3, "ADM").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Location_Code", SqlDbType.Char, 8, "ADM_OFC").Value = DBNull.Value
    cmd.Parameters.Add("@OE_Remarks", SqlDbType.VarChar, 1000, "ACTIVE").Value = DBNull.Value

    cmd.Parameters("@OE_ID").Value = txtOEID.Text
    cmd.Parameters("@OE_Category").Value = cmbCategory.Text
    cmd.Parameters("@OE_SubCategory").Value = cmbSubCategory.Text
    cmd.Parameters("@OE_Name").Value = txtName.Text
    cmd.Parameters("@OE_User").Value = txtUser.Text
    cmd.Parameters("@OE_Brand").Value = cmbBrand.Text
    cmd.Parameters("@OE_Model").Value = cmbModel.Text
    cmd.Parameters("@OE_Specs").Value = txtSpecs.Text
    cmd.Parameters("@OE_SerialNo").Value = txtSerialNo.Text
    cmd.Parameters("@OE_PropertyNo").Value = txtPropertyNo.Text
    cmd.Parameters("@OE_MacAddress").Value = txtMacAddress.Text
    cmd.Parameters("@OE_Static_IP").Value = txtStaticIP.Text
    cmd.Parameters("@OE_Vendor").Value = txtVendor.Text
    cmd.Parameters("@OE_PurchaseDate").Value = dtpPurchaseDate.Value
    cmd.Parameters("@OE_WarrantyInclusiveYear").Value = txtWarrantyInclusiveYear.Text
    cmd.Parameters("@OE_WarrantyStatus").Value = txtWarrantyStatus.Text
    cmd.Parameters("@OE_Status").Value = txtStatus.Text
    cmd.Parameters("@OE_Dept_Code").Value = cmbDeptCode.Text
    cmd.Parameters("@OE_Location_Code").Value = cmbLocationCode.Text
    cmd.Parameters("@OE_Remarks").Value = txtRemarks.Text
    cmd.ExecuteNonQuery()
    sqlconn.Close()
4

4 回答 4

2

?? 运算符可以帮助您轻松检查 Null 值。

例子 :

cmd.Parameters("@OE_ID").Value = txtOEID.Text ?? DBNull.Value;
cmd.Parameters("@OE_Category").Value = cmbCategory.Text ?? DBNull.Value;
于 2013-05-04T03:58:49.450 回答
2

我认为您缺少的是(因为您在过去几天中多次询问过这个问题的变体,是了解表单中的控件如何映射到与您关联的参数SqlCommand,以及如何这些SqlCommand参数映射到您的存储过程的参数。缺乏理解(因为您正在学习,这种缺乏并不是一件坏事)再加上如何处理 NULL 值,这让您感到无所适从。

我不会给你一个问题的单一答案,而是尝试解释整个概念,这样你就可以希望将其应用于编写代码时可能遇到的任何情况。

首先,您的表单上有一个集合TextBoxComboBox控件。这两个控件都有一个Text属性 - 此属性始终返回一个字符串,即使您将 12345 或 10/01/2007 放入其中。这意味着您必须将您获得的字符串转换(转换)为相关存储过程参数的适当数据类型(除非它的 CHAR/VARCHARTextBox.TextComboBox.Text类似的东西)。

创建SqlCommand对象时,您正在向参数集合添加参数。顺便说一句,这是一个非常好的实践,感谢您学习它 - 因为它可以减轻 SQL 注入攻击(在 WinForm 应用程序中并不总是一个高风险,但它是一个很好的编码实践。

SqlParameter您添加的对象SqlCommand需要匹配存储过程中的参数,您也这样做,这很好。但是,看起来您可能正在尝试在第四个参数中传递默认值,而该参数不是用于设置默认值,而是用于在 UPDATE 语句中指定源列。

最后你有你的存储过程。不需要任何参数 - 因此您可以安全地接受任何在表单中没有值的参数。本质上,当您在存储过程的参数上设置默认值(NULL 或其他任何值)时,您可以在调用中省略该参数,SQL Server 将使用您在存储过程的声明中指定的默认值。

您正在按原样在代码中做额外的工作 - 首先将参数全部设置为 null,然后通过将值设置为等于表单上相应控件的值来覆盖该分配。这是您遇到大部分麻烦的地方。

正如其他人至少对您的几个问题所建议的那样,我会检查控件是否有值 - 如果有,则将参数及其值添加到集合中(根据需要进行转换)。这将减少您的“双重”任务。

所以它看起来像这样:

If txtOEID.Text.Trim() <> "" Then
    cmd.Parameters.Add("@OE_ID", SqlDbType.VarChar, 11).Value = txtOEID.Text.Trim()
End If
If cmbCategory.Text.Trim() <> "" Then
    cmd.Parameters.Add("@OE_Category", SqlDbType.Char, 3).Value = cmbCategory.Text.Trim()
End If

等等。当您有一个非 VARCHAR/CHAR 参数时,您需要做一些额外的工作(因为您使用 aDateTimePicker作为购买日期,所以该Value属性已经是 a DateTime,因此您无需担心):

If IsNumeric(txtWarrantyInclusiveYear.Text) Then
    cmd.Parameters.Add("@OE_WarrantyInclusiveYear", SqlDbType.Int).Value = Integer.Parse(txtWarrantyInclusiveYear.Text)
End If

在上述情况下,我建议使用IsNumeric来增加您不会意外尝试解析非数字值的机会(因为您使用的是 VS 2003/.NET 1.1TryParse不可用)。

简而言之,当您在应用程序中创建参数时,您需要了解从用户传入的数据类型,以及存储过程所期望的数据类型。如果它们不匹配,则在将参数添加到集合时,您需要将用户输入转换为存储过程的正确数据类型。

如果参数具有在存储过程中指定的默认值,那么如果用户没有提供值,您可以简单地跳过添加参数。尽管在 NULL 的情况下,请确保您插入的目标列被标记为 NULLABLE。

我强烈建议您放弃 VS 2003 并使用 VS 2012 的Express版本,因为您错过了一大堆功能,这些功能将使您作为程序员的生活更轻松。

如果您需要澄清任何事情,请询问。

于 2013-05-04T04:38:48.230 回答
0

尝试IF对所有值使用内联。

cmd.Parameters("@OE_ID").Value = If(txtOEID.Text.Trim().Length > 0, txtOEID.Text, DBNull.Value)

它的作用是先修剪字符串,然后检查其长度。如果长度大于零,则传递该true部分上的字符串,否则传递DBNull.Value

于 2013-05-04T03:42:38.027 回答
0

由于问题将字符串转换为 int 并且我看到的唯一 int 是@OE_WarrantyInclusiveYear参数。在您的代码中,您可以安全地尝试转换为 int。

Dim year As Integer
If Integer.TryParse(txtWarrantyInclusiveYear.Text, year) Then
 cmd.Parameters("@OE_WarrantyInclusiveYear").Value = year
End If
于 2013-05-04T03:47:48.960 回答