My application was working well but customer wanted me to add some features to it.
Now when I run the app any thing is working but by clicking a button that executes an insert query an exception occurs with this message:
The parameterized query '(#ID int,#Subj nvarchar(50),#Pic varbinary(8000),#LetDate date,#' expects the parameter '#Pic', which was not supplied.
what are those silly parentheses?
the code of this part of program:
conn.Open();
string sqlcmd = "Insert into Pictures (ID, Subj, Pic, LetDate, LetTitle) Values (#ID, #Subj, #Pic, #LetDate, #LetTitle)";
insertCommand = new SqlCommand(sqlcmd, conn);
// For image data, we save the bytes into the database. We save the image to the JPG format bytes.
insertCommand.Parameters.Add("ID", SqlDbType.Int).Value = (++lastID);
insertCommand.Parameters.Add("Subj", SqlDbType.NVarChar, 50).Value = textBox1.Text;
insertCommand.Parameters.Add("Pic", SqlDbType.VarBinary).Value = dynamicDotNetTwain1.SaveImageToBytes(lastIndex, Dynamsoft.DotNet.TWAIN.Enums.DWTImageFileFormat.WEBTW_JPG);
insertCommand.Parameters.Add("LetDate", SqlDbType.Date).Value = dateTimeSelector1.Value.Value.Date;
insertCommand.Parameters.Add("LetTitle", SqlDbType.NText).Value = titleTextBox1.Text;
index++;
int queryResult = insertCommand.ExecuteNonQuery();
if (queryResult == 1)
MessageBox.Show("تصویر با موفقیت در پایگاه داده ذخیره شد", "پیغام", MessageBoxButtons.OK, MessageBoxIcon.Information);
conn.Close();
This is an error occuring elsewhere in your program, and is unrelated to your stored procedure execution code.
The SQL error message "expects the parameter '#VariableName', which was not supplied." usually indicates that you are setting a parameter value to null. If you actually intend to pass NULL to the query, you have to use the DBNull.Value value. However, it looks like you are trying to pass an actual value. Thus, the source of your issue is this line:
insertCommand.Parameters.Add("Pic", SqlDbType.VarBinary).Value = dynamicDotNetTwain1.SaveImageToBytes(lastIndex, Dynamsoft.DotNet.TWAIN.Enums.DWTImageFileFormat.WEBTW_JPG);
If you can figure out why the dynamicDotNetTwain1.SaveImageToBytes() function is returning null and get that function working as expected, then you're stored procedure will work as expected.
I think you have forgot to put # infront of the variable names...
insertCommand.Parameters.Add("#ID", SqlDbType.Int).Value = (++lastID);
insertCommand.Parameters.Add("#Subj", SqlDbType.NVarChar, 50).Value = textBox1.Text;
insertCommand.Parameters.Add("#Pic", SqlDbType.VarBinary).Value = dynamicDotNetTwain1.SaveImageToBytes(lastIndex, Dynamsoft.DotNet.TWAIN.Enums.DWTImageFileFormat.WEBTW_JPG);
insertCommand.Parameters.Add("#LetDate", SqlDbType.Date).Value = dateTimeSelector1.Value.Value.Date;
insertCommand.Parameters.Add("#LetTitle", SqlDbType.NText).Value = titleTextBox1.Text;
Related
I keep getting the error in the title when i am trying to pass data to my database using a c# windows form.
For reference, I am trying to use the Scope_Identity to get the current PK from one table and then pass it to another table as a FK. But i am having trouble making this work. I have no doubt I am missing something or doing something wrong, but I honestly cannot find a solution to what I need. Here is the code I am using.
SqlConnection con = new SqlConnection(#"");
con.Open();
{
using (SqlCommand cmd = new SqlCommand("INSERT dbo.Booking(CustomerID,VehicleID,DateofBooking," +
"DurationBooked, ExpectedReturnDate) VALUES( #CustID, #VehicleID, #DOBooking, #DurationBooked,#ExpectedReturn); INSERT dbo.Payments (BookingID,PaymentMethod,Discount,PaymentAmount," +
"PaymentDate,PaymentReceived) VALUES( SCOPE_IDENTITY(),#PayMeth,#PayAmount,#PayDate, #PayReceived, #Discount)"))
{
cmd.Connection = con;
cmd.Parameters.Add("#CustID", SqlDbType.Int).Value = comboBox1.ValueMember;
cmd.Parameters.Add("#VehicleID", SqlDbType.Int).Value = comboBox2.ValueMember;
cmd.Parameters.Add("#DOBooking", SqlDbType.Date).Value = datefrom.Text;
cmd.Parameters.Add("#ExpectedReturn", SqlDbType.Date).Value = dateTo.Text;
cmd.Parameters.Add("#DurationBooked", SqlDbType.Float, 3).Value = Duration.Text;
cmd.Parameters.Add("#PayMeth", SqlDbType.VarChar, 15).Value = listBox1.Text;
cmd.Parameters.Add("#PayAmount", SqlDbType.Money).Value = PayAmount.Text;
cmd.Parameters.Add("#PayDate", SqlDbType.Date).Value = DatePay.Text;
cmd.Parameters.Add("#PayReceived", SqlDbType.VarChar, 3).Value = PayReceived.Text;
cmd.Parameters.Add("#Discount", SqlDbType.SmallMoney).Value = Discount.Text;
}
I am having a ridiculous amount of hassle trying to Pass this PK to another Table as a FK For reference, it is the BookingID from the Booking table that i am trying to pass to the Payments table in the BookingID column which is a FK relationship
Error Image
I think you're trying to fight with a different problem.
you have conversion issue, but not PK or FK key consistency.
please check if all the params they you send have the same type as described in your instruction.
It can be also that even your scope_identity() has type different from value.
I don't know if you covered this with Keys constraints
by the way. out of scope. There is also a way to get last id is to use ##IDENTITY.
The ##identity function returns the last identity created in the same session. The scope_identity() function returns the last identity created in the same session and the same scope.
FIXED. Thank you to all those who helped. The issue was indeed with my Parameters, specifically with dates. I needed to change the DataType in SQL server to DateTime, as well as ensuring the query would run in SQL Server first helped.
using (SqlCommand cmd = new SqlCommand("INSERT dbo.Booking(CustomerID,VehicleID,DateofBooking, DurationBooked, ExpectedReturnDate) " +
"VALUES( #CustID, #VehicleID, #DOBooking, #DurationBooked,#ExpectedReturn) SELECT SCOPE_IDENTITY(); " +
"INSERT dbo.Payments (BookingID,PaymentMethod,Discount,PaymentAmount, PaymentDate,PaymentReceived)" +
"VALUES( SCOPE_IDENTITY(),#PayMeth,#Discount,#PayAmount, #PayDate, #PayReceived)"))
{
cmd.Connection = con;
cmd.Parameters.Add("#CustID", SqlDbType.Int).Value = Convert.ToInt32(CustID.SelectedValue);
cmd.Parameters.Add("#VehicleID", SqlDbType.Int).Value = Convert.ToInt32(VehicleID.SelectedValue);
cmd.Parameters.Add("#DOBooking", SqlDbType.DateTime).Value = DateofBooking.Value.Date;
cmd.Parameters.Add("#ExpectedReturn", SqlDbType.DateTime).Value = ExpectedReturnDate.Value.Date;
cmd.Parameters.Add("#DurationBooked", SqlDbType.Float, 3).Value = Duration.Text;
cmd.Parameters.Add("#PayMeth", SqlDbType.VarChar, 15).Value = PaymentMethod.Text;
cmd.Parameters.Add("#PayAmount", SqlDbType.Money).Value = PayAmount.Text;
cmd.Parameters.Add("#PayDate", SqlDbType.DateTime).Value = PayDate.Value.Date;
cmd.Parameters.Add("#PayReceived", SqlDbType.VarChar, 3).Value = Received.Text;
cmd.Parameters.Add("#Discount", SqlDbType.VarChar, 3).Value = Discount.Text;
if (cmd.ExecuteNonQuery() > 0)
{
MessageBox.Show("Record inserted");
}
else
{
MessageBox.Show("Customer failed");
}
For Ref, Scope_Identity worked perfectly.
Thanks for all your support, I know this may seem basic for some of you, but i am new to all this and trying to self teach, so as you can imagine.. it was a relief even this little issue is solved. Thanks guys
I am writing a C# application that will access a MySQL Database using a stored procedure with 5 parameters:
in startTime varchar(20),
in endTime varchar(20),
in tagID Int,
in FullDay Int,
in iteration Int
that returns 3 variables all integers.
When executing the MySQLCommand I get the error: "Data too long for column 'startTime' at row 41".
Here is my code:
//create command
MySqlCommand cmd = new MySqlCommand("GetArchiveData", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("startTime", startIn);
cmd.Parameters["startTime"].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("endTime", endIn);
cmd.Parameters["endTime"].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("tagID", tagIn);
cmd.Parameters["tagID"].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("FullDay", fdIn);
cmd.Parameters["FullDay"].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("iteration", iterationIn);
cmd.Parameters["iteration"].Direction = ParameterDirection.Input;
if (cmd.Connection.State == ConnectionState.Closed)
{
cmd.Connection.Open();
}
MySqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
TagData tagData = new TagData();
tagData.TagID = tagIn;
tagData.Dsttimestamp = Convert.ToInt32(dr["timestamp"]);
tagData.PvValue = Convert.ToInt32(dr["sp"]);
tagData.PvValue = Convert.ToInt32(dr["pv"]);
tagDataList.Add(tagData);
}
dr.Close();
this.CloseConnection();
return tagDataList;
If anyone knows why this would happen and why the first occurrence would be row 41 it would be greatly appreciated.
UPDATE:
Removing the Single quotations that are required in the MySQL statement in workbench from the strings startIn and endIn has solved that issue. MySQL uses single quotes to define strings where the C# variable is already declared as a string.
It looks like your problem is in the sproc.
Have you looked at the vaklue you are passing in to it?
It just seems the value is too long for the column so looking at what is being passed will let you know for sure.
Inserting value is too long for the column.
Please debug and Check whether u are inserting correct type of data or correct type value for the column.
There is an hard limit on how much data can be stored in a single row of a mysql table, regardless of the number of columns or the individual column length.
I have a stored procedure that goes like this:
ALTER PROCEDURE [dbo].[AuthenticateUser]
#AzUserName varchar(20),
#Hash varchar(32),
#UserId bigint output,
#Authorized bit output
...
and runs just fine fine in Management Studio.
Here's my C# code:
SqlConnection scon = new SqlConnection(connectionString);
SqlCommand authCmd = new SqlCommand("AuthenticateUser", scon);
authCmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter userNameParam = authCmd.Parameters.Add("#AzUserName", System.Data.SqlDbType.VarChar, 20);
userNameParam.Value = username;
string hashed = Md5Hash.ComputeHash(username);
SqlParameter hashedParam = authCmd.Parameters.Add("#Hash", System.Data.SqlDbType.VarChar, 32);
hashedParam.Value = hashed;
SqlParameter userIdParam = authCmd.Parameters.Add("#UserId", System.Data.SqlDbType.Int);
userIdParam.Direction = System.Data.ParameterDirection.ReturnValue;
SqlParameter authorizedParam = authCmd.Parameters.Add("#Authorized", System.Data.SqlDbType.Bit);
authorizedParam.Direction = System.Data.ParameterDirection.ReturnValue;
scon.Open();
authCmd.ExecuteNonQuery();
scon.Close();
When I run it I am getting the following error:
{"Procedure or function 'AuthenticateUser' expects parameter '#UserId', which was not supplied."} System.Exception {System.Data.SqlClient.SqlException}
When I replace ParameterDirection.ReturnValue with ParameterDirection.Output I am not getting the error but never get the value of the procedure.
UPDATE:
Thank you All for your help. The error was more trivial than you would have thought and I described in the question. I have been changing back and forth ReturnValue to Output for quite a while today with no result. Then I had to post my question on SO just to realize that I am taking the hash value of ... username..Going outdoor to get some oxygen now.
You will have to use ParameterDirection.Output on every parameter, that has been marked with output in T-SQL. You can access the values, after the call to
authCmd.ExecuteNonQuery();
by getting the values of the parametes like this:
authCmd.Parametes["#UserId"].Value
You're confusing the concepts of OUTPUT and RETURN values.
A RETURN value from a stored procedure is a single integer value per stored procedure that is defined within your proc by using the RETURN statement eg
RETURN 1
A stored procedure can have zero to many parameters of which zero to many can be defined as OUTPUT.
In your case you're not showing any use of the RETURN statement but you are using OUTPUT parameters. In SQL Server these are more like input/output parameters and you need to provide a value.
You can access the resulting value of an OUTPUT parameter by looking at the parameters collection after calling the stored procedure and look at the value eg
authCmd.Parameters[2].Value
Or
userIdParam.Value
As per other answers, you need to use the output parameter direction to achieve this
You can access the values of authorizedParam.Value and userIdParam.Value after executing the command.
SqlConnection scon = new SqlConnection(connectionString);
SqlCommand authCmd = new SqlCommand("AuthenticateUser", scon);
authCmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter userNameParam = authCmd.Parameters.Add("#AzUserName", System.Data.SqlDbType.VarChar, 20);
userNameParam.Value = username;
string hashed = Zonal.Pie.Core.Common.Utils.Md5Hash.ComputeHash(username);
SqlParameter hashedParam = authCmd.Parameters.Add("#Hash", System.Data.SqlDbType.VarChar, 32);
hashedParam.Value = hashed;
SqlParameter userIdParam = authCmd.Parameters.Add("#UserId", System.Data.SqlDbType.Int);
userIdParam.Direction = System.Data.ParameterDirection.Output;
SqlParameter authorizedParam = authCmd.Parameters.Add("#Authorized", System.Data.SqlDbType.Bit);
authorizedParam.Direction = System.Data.ParameterDirection.Output;
scon.Open();
authCmd.ExecuteNonQuery();
//Access authorizedParam.Value and userIdParam.Value here
scon.Close();
I seem have come across a short coming with ODBC and DB2 when running stored procedures. It seems that it is not possible to return data from a stored procedure, and I have a prexisting query that I need to use. Has anyone got around this particular issue?
Thanks in advance
Update
The code that I am calling is as follows (assuming that the connection is already opened):
string BaseSQL = "CALL B6009822.O#04666803.PUT";
OdbcCommand command = new OdbcCommand(BaseSQL, myConnection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#Owner", OdbcType.VarChar).Value = "MH";
int rows = command.ExecuteNonQuery();
myConnection.Close();
I get the following error ..
ERROR [HY000] [IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0440 - Routine PUT in O#04666803 not found with specified parameters.
It seems to be objecting to the catalog/library and procedure name. Any idea on what I need to do to get the procedure called ?
Second Update - real example
string BaseSQL = "{ CALL B6009822.O#04666803.PUT(?,?,?,?,?,?,?,?,?) }";
OdbcCommand command = myConnection.CreateCommand();
command.CommandText = BaseSQL;
//OdbcCommand command = new OdbcCommand(BaseSQL, myConnection);
command.CommandType = CommandType.StoredProcedure;
/*
#Param1 VarChar(4), #Param2 dec(8,0),
#Param3 dec(4,0), #Param4 dec(8,0),
#Param5 VarChar(60), #Param6 dec(9,2),
#Param7 dec(9,0), #Param8 dec(9,2),
#Param9 VarChar(10))
*/
command.Parameters.Add("#Param1", OdbcType.VarChar, 4).Value = "MH";
command.Parameters.Add("#Param2", OdbcType.Decimal, 8).Value = 20110217;
command.Parameters.Add("#Param3", OdbcType.Decimal, 4).Value = 1;
command.Parameters.Add("#Param4", OdbcType.Decimal, 8).Value = 178377;
command.Parameters.Add("#Param5", OdbcType.VarChar, 60).Value = "Description";
command.Parameters.Add("#Param6", OdbcType.Decimal, 9).Value = 0;
command.Parameters.Add("#Param7", OdbcType.Decimal, 9).Value = 45;
command.Parameters.Add("#Param8", OdbcType.Decimal, 9).Value = 0;
command.Parameters.Add("#Param9", OdbcType.VarChar, 10).Value = "*CREATE";
int rows = command.ExecuteNonQuery();
myConnection.Close();
Have you tried the CALL syntax?
http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.odbc/db2z_odbcspcall.htm
EDIT: Just in case my comment above is correct:
From this resource, have you tried:
string BaseSQL = "CALL B6009822.O#04666803.PUT (?)";
Important: Unlike ODBC, DB2 ODBC does
not support literals as procedure
arguments. You must use parameter
markers to specify a procedure
parameter.
First of all I had to make the library (or whatever the proper term is) visible in the "System i Navigator". It seems that there is an issue with stored procedures that return results, so I had to call it as a SELECT, as shown below ...
"SELECT PUT('{4}',{1},1,{0},'{2}',0,{3},0,'{5}') as A from LIBRARY.EARNER where EAR = '{4}'"
Not sure if this helps anyone else other than me though!
For any DB2 n00bs like myself hitting this page searching for answers to "SQL0440 - Routine [YourRoutine] in [*N | LIBRARY] not found with specified parameters"...
For me, my problem was where I had defined the constant for the stored procedure name, like so:
// Database Constants
public const string DB_PROC_GET_MYPROC = #"LIBRARY.MYPROC";
How I should have declared it was:
// Database Constants
public const string DB_PROC_GET_MYPROC = #"LIBRARY.MYPROC(#stateCode, #productCode, #tranType)";
...with the parameters included.
I've spent so long with Entity Framework, I have all but forgotten direct database connection basics in c#.
Hope this saves someone some time.
I have a .NET 3.5 web application which has a set of classes handling entity persistence. The INSERT and SELECT prepared commands work. However the UPDATE command never works (no database record is updated) and it never throws an exception. Also it always returns 1, so even the command.ExecuteNonQuery() returns a valid number of affected rows.
Now when I take the same entity class and run it in a test console application, the prepared statement works.
This is really frustrating and a complete show stopper. I have even tried this in Mono on Ubuntu, Mac OS X and Windows. All perform the same (no records updated in web app, insert works, and console app works).
public void Store()
{
SqlConnection conn = new SqlConnection(this.connection_string);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
int i = 0;
if (this.id == 0)
{
// INSERT a new RECORD
cmd.CommandText = "INSERT INTO [VtelCenter] ([CommonName],[Location]) VALUES (#commonname, " +
"#location)";
cmd.Parameters.Add("#commonname", SqlDbType.NVarChar, this.CommonName.Length);
cmd.Parameters["#commonname"].Value = this.CommonName;
cmd.Parameters.Add("#location", SqlDbType.NVarChar, this.Location.Length);
cmd.Parameters["#location"].Value = this.Location;
}
else
{
// UPDATE an existing RECORD
cmd.CommandText = "UPDATE [VtelCenter] SET [CommonName] = #commonname, [Location] = #location, " +
"[Status] = #status WHERE [ID] = #id";
//cmd.CommandText = "EXEC [dbo].[UpdateVtelCenter] #id, #commonname, #location, #status";
cmd.Parameters.Add("#commonname", SqlDbType.NVarChar, this.commonName.Length);
cmd.Parameters["#commonname"].Value = this.CommonName;
cmd.Parameters.Add("#location", SqlDbType.NVarChar, this.Location.Length);
cmd.Parameters["#location"].Value = this.Location;
cmd.Parameters.Add("#status", SqlDbType.Int);
cmd.Parameters["#status"].Value = (int) this.Status;
cmd.Parameters.Add("#id", SqlDbType.Int);
cmd.Parameters["#id"].Value = this.Id;
}
cmd.Prepare();
i = cmd.ExecuteNonQuery();
if (i != 1)
throw new Exception(string.Format("Incorrect number of records stored: {0}, should be 1.", i));
conn.Close();
}
A couple of thoughts to help with debugging this.
Look for any UPDATE triggers (either AFTER or INSTEAD OF) on the VtelCenter table that might be changing your expected results.
Run a SQL Profiler trace on your database server so you can capture the query being passed in on that side.