我正在开发一个ADO.NET应用程序。在DAL中的某个时刻,我调用名为“CREATE_CUSTOMER”的存储过程。虽然我设置了SHORT_NAME字段,但仍然可以获得
"Msg 515, Level 16, State 2, Procedure CREATE_CUSTOMER, Line 29
Cannot insert the value NULL into column 'SHORT_NAME', table 'MYDB.app.CUSTOMER';
column does not allow nulls. INSERT fails." error.
当我使用SQL事件探查器检查查询时,我在服务器上运行以下SQL。当我将它复制并粘贴到新的查询窗口时,我仍然得到相同的错误。
我错过了什么吗?
declare @p16 int
set @p16=NULL
exec sp_executesql N'[app].[CREATE_CUSTOMER]',
N'@SHORT_NAME nvarchar(11),
@MAIL_NAME nvarchar(18),
@MT_SALESPERSON_ID int,
@CREDIT_LIMIT decimal(1,0),
@CREDIT_LIMIT_CURRENCY_ID int,
@PAYMENT_TYPE_ID int,
@SALES_TERM_ID int,
@FREE_STORAGE_DAY_ID int,
@RISK_GROUP_ID int,
@SECTOR_ID int,
@OCCUPATION_ID int,
@STORAGE_FEE_ID int,
@STATUS smallint,
@IDENTITY int output',
@SHORT_NAME=N'NEW Corp',
@MAIL_NAME=N'NEW Corporation',
@MT_SALESPERSON_ID=3,
@CREDIT_LIMIT=0,
@CREDIT_LIMIT_CURRENCY_ID=1,
@PAYMENT_TYPE_ID=4,
@SALES_TERM_ID=7,
@FREE_STORAGE_DAY_ID=6,
@RISK_GROUP_ID=3,
@SECTOR_ID=13,
@OCCUPATION_ID=16,
@STORAGE_FEE_ID=6,
@STATUS=0,
@IDENTITY=@p16 output
select @p16
我的存储过程如下:
CREATE PROCEDURE [app].[CREATE_CUSTOMER]
@SHORT_NAME varchar(250) = NULL,
@MAIL_NAME varchar(500) = NULL,
@MT_SALESPERSON_ID int = NULL,
@CREDIT_LIMIT decimal(18,2) = NULL,
@CREDIT_LIMIT_CURRENCY_ID int = NULL,
@PAYMENT_TYPE_ID int = NULL,
@SALES_TERM_ID int = NULL,
@FREE_STORAGE_DAY_ID int = NULL,
@RISK_GROUP_ID int = NULL,
@SECTOR_ID int = NULL,
@OCCUPATION_ID int = NULL,
@STORAGE_FEE_ID int = NULL,
@STATUS tinyint = NULL,
@IDENTITY INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [app].[CUSTOMER]
([SHORT_NAME],
[MAIL_NAME],
[MT_SALESPERSON_ID],
[CREDIT_LIMIT],
[CREDIT_LIMIT_CURRENCY_ID],
[PAYMENT_TYPE_ID],
[SALES_TERM_ID],
[FREE_STORAGE_DAY_ID],
[RISK_GROUP_ID],
[SECTOR_ID],
[OCCUPATION_ID],
[STORAGE_FEE_ID],
[STATUS],
[CREATE_DATE],
[CREATE_USERID])
VALUES
(@SHORT_NAME,
@MAIL_NAME,
@MT_SALESPERSON_ID,
@CREDIT_LIMIT,
@CREDIT_LIMIT_CURRENCY_ID,
@PAYMENT_TYPE_ID,
@SALES_TERM_ID,
@FREE_STORAGE_DAY_ID,
@RISK_GROUP_ID,
@SECTOR_ID,
@OCCUPATION_ID,
@STORAGE_FEE_ID,
@STATUS,
GETDATE(),
CONTEXT_INFO())
SELECT @IDENTITY = SCOPE_IDENTITY()
END
此SQL代码由ADO.NET生成。实际的C#代码是:
private static ICustomer CreateCustomer(ICustomer customer, int contextUserId)
{
try
{
string sql = "[app].[CREATE_CUSTOMER]";
SqlConnection conn = null;
using (conn = GetConnection())
{
SetContextInfomationToConnection(conn, contextUserId);
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@SHORT_NAME", customer.ShortName);
cmd.Parameters.AddWithValue("@MAIL_NAME", customer.MailName);
cmd.Parameters.AddWithValue("@MT_SALESPERSON_ID", customer.SalesPersonId);
cmd.Parameters.AddWithValue("@CREDIT_LIMIT", customer.CreditLimit);
cmd.Parameters.AddWithValue("@CREDIT_LIMIT_CURRENCY_ID", customer.CreditLimitCurrencyId);
cmd.Parameters.AddWithValue("@PAYMENT_TYPE_ID", customer.PaymentTypeId);
cmd.Parameters.AddWithValue("@SALES_TERM_ID", customer.SalesTermId);
cmd.Parameters.AddWithValue("@FREE_STORAGE_DAY_ID", customer.FreeStorageDayId);
cmd.Parameters.AddWithValue("@RISK_GROUP_ID", customer.RiskGroupId);
cmd.Parameters.AddWithValue("@SECTOR_ID", customer.SectorId);
cmd.Parameters.AddWithValue("@OCCUPATION_ID", customer.OccupationId);
cmd.Parameters.AddWithValue("@STORAGE_FEE_ID", customer.StorageFeeId);
cmd.Parameters.AddWithValue("@STATUS", customer.Status);
SqlParameter prmNewId = new SqlParameter("@IDENTITY", SqlDbType.Int, 4);
prmNewId.Direction = ParameterDirection.Output;
cmd.Parameters.Add(prmNewId);
cmd.ExecuteNonQuery();
int id = prmNewId.Value != DBNull.Value ? (int)prmNewId.Value : -1;
if (id > 0)
{
customer.Id = id;
return customer;
}
else
{
throw new Exception("Can not insert customer record with Id generation");
}
}
}
catch (Exception ex)
{
throw;
}
}
答案 0 :(得分:1)
您的代码相当于这样做:
DECLARE @SHORT_NAME nvarchar(11) = N'NEW Corp';
...
EXEC [app].[CREATE_CUSTOMER];
您只是声明参数,从未实际将它们传递给过程调用。你的代码应该是这样的:
exec sp_executesql N'[app].[CREATE_CUSTOMER] @SHORT_NAME, @MAIL_NAME, ...',
N'@SHORT_NAME nvarchar(11),
@MAIL_NAME nvarchar(18),
...',
@SHORT_NAME=N'NEW Corp',
@MAIL_NAME=N'NEW Corporation',
...
您不仅必须声明传递给批处理的参数,还必须在调用该程序时使用它们。
当我使用SQL事件探查器检查查询时,我在服务器上运行以下SQL。当我将它复制并粘贴到新的查询窗口时,我仍然得到相同的错误
这听起来很可疑,就像您使用的是SqlCommand
,但忘了将CommandType
设置为Procedure
。默认值为Text
,其行为与您观察到的完全相同。
答案 1 :(得分:0)
不要为ur变量赋值空值,只能尝试将其声明为
DECLARE @SHORT_NAME varchar(250),
而不是
@SHORT_NAME varchar(250)= NULL,