对象不能从 DBNull 转换为带输出参数的存储过程中的其他类型
Object cannot be cast from DBNull to other types in stored procedure with output parameter
我想在 C# 应用程序中使用 SQL 服务器的存储过程,该应用程序 return 是一个输出参数,但 在尝试了许多不同的方法后 我还没有意识到如何做到这一点。
此程序应 return 一个 variable/parameter 称为 "recargo"(附加费),其值因客户的年龄、性别和婚姻状况而异。
该程序还有一个输入参数,即客户端的 ID
应用程序 return 是一个 DBNull 异常,我已经尝试用代码修复它,但它仍然没有 return 值。它总是 return 为 null。
CREATE OR ALTER PROCEDURE CalcularRecargo
@rut NVARCHAR(10),
@recargo DECIMAL OUTPUT
AS
BEGIN
DECLARE @fecha DATETIME,
@sexo TINYINT,
@ecivil TINYINT,
@edad INT
SELECT
@fecha = cl.FechaNacimiento,
@sexo = cl.IdSexo,
@ecivil= cl.IdEstadoCivil
FROM
Contrato c
JOIN
Cliente cl ON c.RutCliente = cl.RutCliente
WHERE
c.RutCliente = @rut
--HERE I CALCULATE THE AGE, I DON'T KNOW IF THIS IS CORRECT
BEGIN
SET @edad = (CONVERT(INT, CONVERT(CHAR(8), GETDATE(), 112)) - CONVERT(CHAR(8), @fecha, 112)) / 10000
END
--if the age is between some of these ranges, the surcharge (@recargo) should be increased.
IF @edad >= 18 AND @edad <=25
BEGIN
SET @recargo = @recargo + 3.6
END
ELSE IF @edad >=26 AND @edad <=45
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 6
END
--same with gender.
IF @sexo = 1
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 1.2
END
--same with marital status
IF @ecivil = 1
BEGIN
SET @recargo = @recargo + 4.8
END
ELSE IF @ecivil = 2
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 3.6
END
RETURN
END;
这是该方法的 C# 代码:
public static double CalcularRecargo(string rut)
{
double recargo = 0.0;
SqlConnection conexion = new SqlConnection(ConSql.conexion);
try
{
conexion.Open();
SqlCommand cmd = new SqlCommand("CalcularRecargo", conexion);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter ParRut = new SqlParameter("@rut", SqlDbType.VarChar);
ParRut.Value = rut;
cmd.Parameters.Add(ParRut);
SqlParameter ParRecargo = new SqlParameter("@recargo", SqlDbType.Decimal);
//ParRecargo.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ParRecargo).Direction=ParameterDirection.Output;
cmd.ExecuteNonQuery();
// IF I UNCOMMENT AND USE THIS CODE IT STILL RETURNS A NULL.
var prerecargo = cmd.Parameters["@recargo"].Value;
if (prerecargo != DBNull.Value)
@recargo = Convert.ToDouble(prerecargo);
// IF I UNCOMMENT AND USE THE CODE BELOW IT RETURNS THE DBNULL EXCEPTION
// recargo = Convert.ToDouble(cmd.Parameters["@recargo"].Value);
}
catch(Exception error)
{
MessageBox.Show(error.Message);
}
finally
{
conexion.Close();
}
return recargo;
}
这是我实现它的 C# 代码的另一部分:
private void button1_Click(object sender, EventArgs e)
{
double recargo = 0;
double primaanual = 0;
double primamensual = 0;
if (ComboTitular.Text != "")
{
recargo = Contrato.CalcularRecargo(ComboTitular.Text);
}
if (recargo > 0 && ComboPlan.Text != "")
{
primaanual = Plan.planes.Find(i => i.Nombre == ComboPlan.Text).PrimaBase + recargo;
primamensual = primaanual / 12;
LblPrimaAnual.Text = primaanual.ToString();
LblPrimaMensual.Text = primamensual.ToString();
}
else
{
MessageBox.Show("Seleccione un plan por favor");
}
try
{
Contrato con = new Contrato(numcontrato, feccreacion, fectermino, ComboTitular.Text, ComboPlan.Text, poliza, inivig, finvig, estavig, declarasalud, primaanual, primamensual, observacion);
string resultado = con.AgregarContrato(con);
MessageBox.Show(resultado);
}
catch (Exception error)
{
MessageBox.Show("Contract already exists");
}
}
注意:我删除了很多额外的代码以使问题更清楚
提前致谢
我认为问题是 @recargo 是 NULL 因为它在计算之前从未被赋予初始值。
在下方查找快速重现和文档link了解更多详情:
All arithmetic operators (+, -, *, /, %), bitwise operators (~, &, |),
and most functions return null if any of the operands or arguments is
null, except for the property IsNull Find more details at
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/handling-null-values
DECLARE @recargo DECIMAL
-- @recargo is NULL
SELECT @recargo
SET @recargo = @recargo + 2.4
SELECT @recargo --NULL
SET @recargo = 0 --INITIALIZING THE VARIABLE
SET @recargo = @recargo + 2.4
-- @recargo is 2
SELECT @recargo
我想在 C# 应用程序中使用 SQL 服务器的存储过程,该应用程序 return 是一个输出参数,但 在尝试了许多不同的方法后 我还没有意识到如何做到这一点。
此程序应 return 一个 variable/parameter 称为 "recargo"(附加费),其值因客户的年龄、性别和婚姻状况而异。 该程序还有一个输入参数,即客户端的 ID
应用程序 return 是一个 DBNull 异常,我已经尝试用代码修复它,但它仍然没有 return 值。它总是 return 为 null。
CREATE OR ALTER PROCEDURE CalcularRecargo
@rut NVARCHAR(10),
@recargo DECIMAL OUTPUT
AS
BEGIN
DECLARE @fecha DATETIME,
@sexo TINYINT,
@ecivil TINYINT,
@edad INT
SELECT
@fecha = cl.FechaNacimiento,
@sexo = cl.IdSexo,
@ecivil= cl.IdEstadoCivil
FROM
Contrato c
JOIN
Cliente cl ON c.RutCliente = cl.RutCliente
WHERE
c.RutCliente = @rut
--HERE I CALCULATE THE AGE, I DON'T KNOW IF THIS IS CORRECT
BEGIN
SET @edad = (CONVERT(INT, CONVERT(CHAR(8), GETDATE(), 112)) - CONVERT(CHAR(8), @fecha, 112)) / 10000
END
--if the age is between some of these ranges, the surcharge (@recargo) should be increased.
IF @edad >= 18 AND @edad <=25
BEGIN
SET @recargo = @recargo + 3.6
END
ELSE IF @edad >=26 AND @edad <=45
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 6
END
--same with gender.
IF @sexo = 1
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 1.2
END
--same with marital status
IF @ecivil = 1
BEGIN
SET @recargo = @recargo + 4.8
END
ELSE IF @ecivil = 2
BEGIN
SET @recargo = @recargo + 2.4
END
ELSE
BEGIN
SET @recargo = @recargo + 3.6
END
RETURN
END;
这是该方法的 C# 代码:
public static double CalcularRecargo(string rut)
{
double recargo = 0.0;
SqlConnection conexion = new SqlConnection(ConSql.conexion);
try
{
conexion.Open();
SqlCommand cmd = new SqlCommand("CalcularRecargo", conexion);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter ParRut = new SqlParameter("@rut", SqlDbType.VarChar);
ParRut.Value = rut;
cmd.Parameters.Add(ParRut);
SqlParameter ParRecargo = new SqlParameter("@recargo", SqlDbType.Decimal);
//ParRecargo.Direction = ParameterDirection.Output;
cmd.Parameters.Add(ParRecargo).Direction=ParameterDirection.Output;
cmd.ExecuteNonQuery();
// IF I UNCOMMENT AND USE THIS CODE IT STILL RETURNS A NULL.
var prerecargo = cmd.Parameters["@recargo"].Value;
if (prerecargo != DBNull.Value)
@recargo = Convert.ToDouble(prerecargo);
// IF I UNCOMMENT AND USE THE CODE BELOW IT RETURNS THE DBNULL EXCEPTION
// recargo = Convert.ToDouble(cmd.Parameters["@recargo"].Value);
}
catch(Exception error)
{
MessageBox.Show(error.Message);
}
finally
{
conexion.Close();
}
return recargo;
}
这是我实现它的 C# 代码的另一部分:
private void button1_Click(object sender, EventArgs e)
{
double recargo = 0;
double primaanual = 0;
double primamensual = 0;
if (ComboTitular.Text != "")
{
recargo = Contrato.CalcularRecargo(ComboTitular.Text);
}
if (recargo > 0 && ComboPlan.Text != "")
{
primaanual = Plan.planes.Find(i => i.Nombre == ComboPlan.Text).PrimaBase + recargo;
primamensual = primaanual / 12;
LblPrimaAnual.Text = primaanual.ToString();
LblPrimaMensual.Text = primamensual.ToString();
}
else
{
MessageBox.Show("Seleccione un plan por favor");
}
try
{
Contrato con = new Contrato(numcontrato, feccreacion, fectermino, ComboTitular.Text, ComboPlan.Text, poliza, inivig, finvig, estavig, declarasalud, primaanual, primamensual, observacion);
string resultado = con.AgregarContrato(con);
MessageBox.Show(resultado);
}
catch (Exception error)
{
MessageBox.Show("Contract already exists");
}
}
注意:我删除了很多额外的代码以使问题更清楚
提前致谢
我认为问题是 @recargo 是 NULL 因为它在计算之前从未被赋予初始值。
在下方查找快速重现和文档link了解更多详情:
All arithmetic operators (+, -, *, /, %), bitwise operators (~, &, |), and most functions return null if any of the operands or arguments is null, except for the property IsNull Find more details at https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/handling-null-values
DECLARE @recargo DECIMAL
-- @recargo is NULL
SELECT @recargo
SET @recargo = @recargo + 2.4
SELECT @recargo --NULL
SET @recargo = 0 --INITIALIZING THE VARIABLE
SET @recargo = @recargo + 2.4
-- @recargo is 2
SELECT @recargo