Error converting int to nvarchar - c#

This error has me very confused. I have a stored procedure with two output parameters as defined below
#agentNumber int OUTPUT,
#currentAgentNum int OUTPUT,
They are then populated using the SELECT statements below
SELECT #agentNumber = AgentNumber
FROM AgentIdentification
WHERE AgentTaxId = #ssn
SELECT #currentAgentNum = AgentNumber
FROM UniqueAgentIdToAgentId
WHERE AgentId = #agentId
In the database, AgentNumber is defined in both tables, as an int. However, when I call this stored procedure in my C# code, I get a SQL exception stating:
Error converting data type int to nvarchar.
If I change the data types of the output parameters to nvarchar, the code will execute, however it will only return nothing more than the first digit of the whole number. Below is how the variables are defined in the C# code
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", "");//Output parameter - leave blank
SqlParameter outCurrentAgentNumber = new SqlParameter("#currentAgentNum", "");//Output parameter - leave blank
outNewAgentNumber.Direction = ParameterDirection.Output;
outCurrentAgentNumber.Direction = ParameterDirection.Output;
I add these parameters to a SqlCommand object, specify the appropriate database and commandType, then use .ExecuteNonQuery() to call the procedure. Again, what has me really confused is the error message stating that I'm using nvarchar as a data type, which could only (to the best of my knowledge) be referring to something on the database side. However, as I said I've double/triple checked and both AgentNumber columns are of type int.
EDIT
Changing the sqlParameter declarations to a starting value of 0 has solved this issue. I'm now running into the same problem with two other parameters.
SqlParameter outOperator = new SqlParameter("#operator", "");//Output parameter - leave blank
SqlParameter outDate = new SqlParameter("#date", "");//Output parameter - leave blank

Change
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", "");//Output parameter - leave blank
SqlParameter outCurrentAgentNumber = new SqlParameter("#currentAgentNum", "");//Output parameter - leave blank
to
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", 0);//Output parameter - leave blank
SqlParameter outCurrentAgentNumber = new SqlParameter("#currentAgentNum", 0);//Output parameter - leave blank
In your code, you're initially specifying the value as a string because you are passing it a string, which maps to a varchar when going from the CLR type to the SQL Data Type.
Once the runtime sees it as a string, it retains the same type throughout code, so if you assign a numeric (int) value, it still sees it as a string. The trick is to assign it the correct data type in the first place.

These two lines are the culprits:
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", "");
SqlParameter outCurrentAgentNumber = new SqlParameter("#currentAgentNum", "");
By specifying an empty string ("") as the second parameter, the ADO.NET runtime assumes it's a string paramter. And since you didn't specify any lengths - it probably defaults to just one character length (that's why it's returning only the first digit).
So, my recommendation would be to always explicitly define the datatype (and if it's a string - also define a length!) for your SQL parameters:
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", SqlDbType.Int);
outNewAgentNumber.Direction = ParameterDirection.Output;
outNewAgentNumber.Value = 0;
or
SqlParameter outNewAgentNumber = new SqlParameter("#agentNumber", SqlDbType.NVarChar, 50);
outNewAgentNumber.Direction = ParameterDirection.Output;
outNewAgentNumber.Value = "";

Related

Why my Access DB rejects an insert date time?

I have this table created on an Access DB.
string sql = $"CREATE TABLE Eventi (" +
$"id AUTOINCREMENT PRIMARY KEY," +
$"tipologia varchar(255)," +
$"denominazione varchar(255)," +
$"descrizione varchar(255)," +
$"data date," +
$"costo decimal," +
$"prezzo decimal" +
$");";
I use this query to insert new records in the table, but when i exec the query it returns me a 'System.Data.OleDb.OleDbException: 'Data type mismatch in criteria expression.'.
cmd.CommandText = "INSERT INTO Eventi (tipologia,denominazione,descrizione,data,costo,prezzo) VALUES " +
"(#tipologia, #denominazione, #descrizione, #data, #costo, #prezzo);";
Here it is the code to add the querie's parameters:
cmd.Parameters.Add("#id", OleDbType.Integer).Value = v.Id;
cmd.Parameters.Add("#tipologia", OleDbType.VarChar, 255).Value = v.Tipologia;
cmd.Parameters.Add("#denominazione", OleDbType.VarChar, 255).Value = v.Denominazione;
cmd.Parameters.Add("#descrizione", OleDbType.VarChar, 255).Value = v.Descrizione;
cmd.Parameters.Add("#data", OleDbType.Date).Value = v.Data.Date;
cmd.Parameters.Add("#costo", OleDbType.Double).Value = v.Costo;
cmd.Parameters.Add("#prezzo", OleDbType.Double).Value = v.Prezzo;
The real problem in your query is not the type difference between decimal and double. While it is really good practice to always express the correct datatype, in this context, the parameters of type double can be easily converted to decimal if the properties Costo and Prezzo are of type decimal.
The real problem is the presence of a first parameter named #ID while you don't have this field in your fields names and in your parameters placeholders.
In OleDb parameters are not recognized by their name and assigned to their placeholders using the name property. (Indeed the documentation tells us to name these placeholders all with the ? character). In OleDb parameters are positional, so the first parameter will be used as the value for the first placeholder. In your code this results in a shift of every parameter by one position leading to the parameter #Descrizione assigned to the field data and of course that string is not a date.
Just remove the first parameter from your collection and everything should be fine.
Side note. In Access, as well in MySql, you can assign a value to an AUTOINCREMENT/AUTONUMBER field if you really want. SqlServer instead doesn't allow this practice without turning off the IDENTITY property of the column.
ID value is not needed because is an autoincrement field.
As Liam point out in comments you need to use OleDbType.Decimal instead of OleDbType.Decimal
Or you can also do not declare the type (it will be decided automatic)
cmd.Parameters.Add(new SqlParameter("#CODE", myCode));

SQL Server Count Using C# Prepared Statement

Im trying to do a COUNT using C# 'Prepared Statements' but I get error: :
SqlCommand.Prepare method requires all variable length parameters to
have an explicitly set non-zero Size
Below is my code:
public int PreparedCheck(String email)
{
SqlCommand cmd = new SqlCommand();
cmd = new SqlCommand("SELECT COUNT(*) FROM [dbo].[AspNetUsers] WHERE Email=#val1", conn);
cmd.Parameters.Add("#val1", SqlDbType.VarChar);
cmd.Prepare();
Int32 count = (Int32) cmd.ExecuteScalar();
return count;
}
Looks like you didn't specify your parameter value.
cmd.Parameters.Add("#val1", SqlDbType.VarChar).Value = email;
I write email as a value because you pass it as a parameter to your PreparedCheck method but you never use it.
Two errors. You don't set the value for the parameter, but you also don't set the size of the parameter as required by the Prepare method
SqlParameter p1 = cmd.Parameters.Add("#val1", SqlDbType.VarChar);
p1.Value = email;
p1.Size = 255; // This should be the size of the column EMail on the datatable
cmd.Prepare();
Simply setting the value of the parameter seems not to be enough for the Prepare method.
While the property size is changed to the string length passed as value, the error is still there and doesn't go away until you explicitly set the Size property to valid value.
This is from the REMARKS section on SqlCommand.Prepare
Before you call Prepare, specify the data type of each parameter in
the statement to be prepared. For each parameter that has a variable
length data type, you must set the Size property to the maximum size
needed. Prepare returns an error if these conditions are not met.
You need to set the value for your parameter:
cmd.Parameters.Add("#val1", SqlDbType.VarChar).Value = email;

Procedure or Function Expects Parameter Which Was Not Supplied #2

I am currently trying to complete a transaction for a web based app, however;
Procedure or function 'completeTransaction' expects parameter '#dateTime', which was not supplied.
Here is copy of the function.
public static void completeTransaction(string storeCode, string employeeId, DateTime Date, string itemListNoId)
{
using (SqlConnection conn = new SqlConnection("Data Source = ; Initial Catalog =Business ; Integrated Security = true;"))
{
using (SqlCommand command = new SqlCommand("dbo.completeTransaction", conn))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#storeCode", SqlDbType.Int).Value = storeCode;
command.Parameters.Add("#employeeId", SqlDbType.Int).Value = employeeId;
**command.Parameters.Add("#Date", SqlDbType.DateTime).Value = Date;**
command.Parameters.Add("#itemListNoId", SqlDbType.Int).Value = itemListNoId;
conn.Open();
command.ExecuteNonQuery();
conn.Close();
}
}
}
My sql table contains the following tables and types (storeCode, INT, employee, INT, Date, DATETIME, itemListNoId, INT)
You do not pass a parameter called #dateTime. It seems like this line
command.Parameters.Add("#Date", SqlDbType.DateTime).Value = Date;
Should be
command.Parameters.Add("#dateTime", SqlDbType.DateTime).Value = Date;
But without the SP source code it is hard to be sure. Keep in mind that SQL Server is complaining about the NAME of the parameter not about its type.
expects parameter '#dateTime'
You passed a parameter named #Date.
the name of the parameter is wrong:
command.Parameters.Add("#dateTime", SqlDbType.DateTime).Value = Date;
If you are getting this and you have passed in the correctly named parameter, check that the CommandType is set to Stored procedure
cmd.CommandType = CommandType.StoredProcedure;
I was seeing these same symptoms spent an embarrassingly long time tracking down how each parameter was getting to the stored proc.
As previous answers have correctly mentioned, most probable reasons for this error are either forgetting to add parameter(s) to the SqlCommand or forgetting to set command's type to CommandType.StoredProcedure
In case you have already set above correctly and still pulling your hair, then this might be the reason.
If you set parameters value to null (e.g. mySQLParam1.Value = valuePassedToMe and if valuePassedToMe is null) then you will get the same error (i.e. Procedure or function '...' expects parameter '...', which was not supplied).
This can be solved by assigning DBNull.Value when the value needs to be null
i.e.
mySQLParam1.Value = valuePassedToMe ?? (object)DBNull.Value;
When you assign null to a parameter ADO.Net converts it to default. Below is an example from SQL Server Profiler.
exec dbo.MyStoredProcedure #mySQLParam1=default,#mySQLParam2=default,#mySQLParam3=default,...
When you assign DBNull.Value the generated SQL becomes:
exec dbo.MyStoredProcedure #mySQLParam1=NULL,#mySQLParam2=NULL,#mySQLParam3=NULL,...

ADO.NET - The Size property has an invalid size of 0

I'm trying to get output value from DB via ADO.NET. There's a client code:
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("pDoSomethingParamsRes", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#i", 1);
var outParam = new SqlParameter("#out", SqlDbType.VarChar);
outParam.Direction = ParameterDirection.Output;
command.Parameters.Add(outParam);
command.ExecuteNonQuery();
Console.WriteLine(command.Parameters["#out"].Value.ToString());
}
When I run this I get the following exception:
the Size property has an invalid size of 0
According to manual SqlParameter.Size Property I might omit size. Why do I get this exception?
How to make it work without passing size?
VarChar and NVarChar are variable width character fields (thus var+char). You have to set the length, otherwise the default is zero.
Parameter Size is required for variable size Output parameters. Generally ADO.NET decides the size of the parameter based on the Value assigned to the parameter (hence it is optional), but in output parameter since no value is Set, you need provide the size required for the parameter
Set the Parameter size to size of the output variable from the DB... Say 50
outParam.Size = 50;
Incidentally, setting the size property of an output parameter is necessary even if it isn't a string-type parameter. For example, if you are using a System.Data.SqlDbType.Int, you should set the size to be 4.
Check MSDN : SqlParameter.Size Property
For bidirectional and output parameters, and return values, you must set the value of Size. This is not required for input parameters, and if not explicitly set, the value is inferred from the actual size of the specified parameter when a parameterized statement is executed.
Everyone's answer was about as clear as mud to me. Maybe this will help someone now that I found what worked.
Need to add size to the parameter
DynamicParameters Params = new DynamicParameters();
Params.Add("#ProfileID", ProfileID);
Params.Add("#CategoryName", CategoryName);
Params.Add("#Added", dbType: DbType.String, direction: ParameterDirection.Output,size:10);
db.Execute(sql, Params, commandType: CommandType.StoredProcedure, commandTimeout: 60);
var Added = Params.Get<string>("#Added");
I'm not sure if this is the same problem i've had before, but using a byte for a parameter can sometimes lead to this error.
Try this. Explicitly declare the i parameter as a variable.
THEN assign it's value with the Value property.
Also, you can get the actual size of the parameters by inspecting the sproc with this little command:
SqlCommandBuilder.DeriveParameters(yourCommand)
and then just foreach your way through the parameters collection.
I had this error occur, supplying a value that had a non-string, but nullable, type. In my case, an int?. I fixed it by passing in a non-nullable int instead.
you have to set Size for parameter output
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
SqlCommand command = new SqlCommand("pDoSomethingParamsRes", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#i", 1);
var outParam = new SqlParameter("#out", SqlDbType.VarChar);
outParam.Direction = ParameterDirection.Output;
outParam.Size = 50; // this is example
command.Parameters.Add(outParam);
command.ExecuteNonQuery();
Console.WriteLine(command.Parameters["#out"].Value.ToString());
}
I had the same error and below is my code that works
cmd.Parameters("#ProjectKey").SqlDbType = SqlDbType.NVarChar
cmd.Parameters("#ProjectKey").Size = 150
cmd.Parameters("#ProjectKey").Direction = ParameterDirection.InputOutput
cmd.ExecuteNonQuery()

C# - ODP.NET and ora-01475 must reparse cursor to change bind variable datatype

I'm getting ora-01475 whenever I try to insert a null value in a column (of type DateTime) after some records have already been inserted that have real date values.
I'm using the OracleParameter constructor that takes the name and the value as an object (I assume the data type is then implied from the datatype of the object), but since sometimes the value of my parameter is null, it's being set as a String, therefore throwing this error.
I don't want to use the constructor that takes the datatype explicitly because I use reflection heavily to build the OracleCommand object and its parameters.
How can I reparse the cursor (as the error suggests) if I find this situation?
Has anyone else run into this and has a solution?
Have you tried to use nullable types?
DateTime? myDate;
//Code to set myDate value...
string sql = "[your SQL]"
using (OracleCommand command = new SqlCommand(sql, cn))
{
OracleParameter param = new OracleParameter(":Name",myDate);
command.Paerameters.add(param);
command.ExecuteNonQuery();
}

Categories