The following code results in a System.Data.SqlClient.SqlException: Timeout expired.
const string sqlStmt = #"SELECT *
FROM CUSTOMER_INFO
WHERE CUSTOMER_NO = #CUSTOMER_NO;";
SqlCommand command = new SqlCommand(sqlStmt, connection);
command.Parameters.AddWithValue("#CUSTOMER_NO", txtAccountNo.Text.Trim().ToUpper());
but this does not time out...
const string sqlStmt = #"SELECT *
FROM CUSTOMER_INFO
WHERE CUSTOMER_NO = #CUSTOMER_NO;";
SqlCommand command = new SqlCommand(sqlStmt, connection);
command.Parameters.Add("#CUSTOMER_NO", SqlDbType.VarChar, 25).Value = txtAccountNo.Text.Trim().ToUpper();
I don't understand why, can anyone enlighten me?
Can you get a look at the SQL statement that gets executed by the database ?
You'll probably see a difference in the type that is used by the parameter. I believe that the AddParamWithValue method will not use the correct type for the parameter.
Then, it is possible that the DBMS will have to convert the value back to the correct type. Some DBMS'es will not be able to use an index-lookup in that case, which will result in a longer running query, hence the timeout.
Related
I am a newbie in DB2 world and am using:
- DB2 Data Provider for .NET (IBM.Data.DB2.dll version 9.7.4.4)
- C# VS2010 with .NET Framework 4.0
I have problem with query that uses parameter.
My code snippet:
DB2Command cmd = new DB2Command();
cmd.CommandText = "SELECT COUNT(*) FROM CUSTOMERS t0 WHERE (t0.\"CITY\" < :p0)";
cmd.Connection = Db2Connection;
DB2Parameter param = cmd.CreateParameter();
param.DB2Type = DB2Type.VarChar;
param.ParameterName = ":p0";
param.Value = "Seattle";
var p = cmd.Parameters.Add(param);
var execResult = cmd.ExecuteScalar();
I get following error on cmd.ExecuteScalar():
The number of variables in the EXECUTE statement, the number of
variables in the OPEN statement, or the number of arguments in an OPEN
statement for a parameterized cursor is not equal to the number of
values required. SQLSTATE=07004
Please help how to fix the problem. Thank you in advance.
Additional information:
1. I just tried to use IBM Data Studio to verify the DB2 command using query editor. It doesn't recognize the prefix "#" for parameter. So I use oracle-liked prefix ":" for it. It works. But my C# code still raises the error [07004] SQL0313N
2. If I don't use any prefix for parameter on my C# code, I get ERROR [42703] [IBM][DB2/NT64] SQL0206N \"P0\" is not valid in this context.
Finally I find out 2 ways to fix the problem.
Using unnamed parameter "?" instead of parameter name ":p0".
DB2Command cmd = new DB2Command();
cmd.CommandText = "SELECT COUNT(*) FROM CUSTOMERS t0 WHERE (t0.\"CITY\" < ?)";
cmd.Connection = Db2Connection;
DB2Parameter param = cmd.CreateParameter();
param.DB2Type = DB2Type.VarChar;
param.ParameterName = "param1";
param.Value = "Seattle";
var p = cmd.Parameters.Add(param);
var execResult = cmd.ExecuteScalar();
Activate HostVarParameters property of class DB2ConnectionStringBuilder and the original code remains unchanged (keeping using named parameters).
My 2 cents,
Mag
I am trying to pass both Column name and the Value to be checked in the code at runtime. However I am getting an "Invalid Column Name " exception.
The code is as follows :
string temp = TextBox1.Text.ToString();
SqlConnection con = new SqlConnection("data source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\Sagar\\Documents\\Test.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True");
SqlCommand com = new SqlCommand("Select * from Employee Where #field = Sagar", con);
com.Parameters.AddWithValue("#field", DropDownList1.SelectedValue.ToString());
//com.Parameters.AddWithValue("#value", temp);
SqlDataAdapter da = new SqlDataAdapter(com);
con.Open();
SqlDataReader reader = com.ExecuteReader();
GridView1.DataSource = reader;
GridView1.DataBind();
The message says that there is no column named 'Sagar' in the table. Is there such a column? Things would be easier if you showed us the table schema instead of having us guess from the error message.
It is not possible to parameterize column names using SqlParameter in C#. This has been discussed here multiple times.
What's happening with the query the way Vidhya Sagar Reddy is doing it, is the following. He assumes that the following query
Select * from Employee Where #field = 'Sagar'
is replaced by this query when setting "Name" as the value for the #field parameter:
Select * from Employee Where Name = 'Sagar'
This, however, is wrong! What's happening is that the #field parameter is replaced as follows:
Select * from Employee Where 'Name' = 'Sagar'
This returns no results, as the WHERE clause is always false. Of course, if you use the field name Sagar, this akways returns true, as the statement then reads:
Select * from Employee Where 'Sagar' = 'Sagar'
Here's an easy test to prove what I've said above. Use the following statement to set the #field parameter (supposed, there's no column named eirghoerihgoh in the table):
com.Parameters.AddWithValue("#field", "eirghoerihgoh");
If the query executes correctly (maybe not returning any results), the above is correct. If it was not correct, an exception should be thrown about the eirghoerihgoh column not being present.
Thank you Vidhya Sagar Reddy for proving my point. By using this line
com.Parameters.AddWithValue("#field", "eirghoerihgoh");
you say you didn't get any results, but you also didn't get an exception. However, if the statement really had been changed to
Select * from Employee Where eirghoerihgoh = 'Sagar'
there had to be an exception saying that there was no column named eirghoerihgoh. As you didn't get that exception, there's only one possible explanation: The statement was changed to
Select * from Employee Where 'eirghoerihgoh' = 'Sagar'
and this executes, but doesn't return results, as the condition is always false.
Instead you can make your code this way, which works perfectly:
"Select * from Employee Where "+DropDownList1.SelectedValue.ToString()+" =
'Sagar'" – Vidhya Sagar Reddy
The reason for that is quite simple, the value that are to be specified in SQL should be in single quotes and this is a simple mistake by the way..!!!!
SqlCommand com = new SqlCommand("Select * from Employee Where #field = 'Sagar'", con);
And even change the parameter to "field" in the following line and not "#field"..!!
com.Parameters.AddWithValue("field", DropDownList1.SelectedValue.ToString());
This is working..>!!!!
I have an Informix database which exposes some stored procedures, I have an abstracted data accessor that handles communicating with them but I have a problem with a null value.
Directly you can call:
execute procedure some_stored_procedure(1,2,NULL,3)
and get back correct results, I would rather there not be this nullable field, but it is out of my hands. Anyway I was originally trying to call it like so:
var command = connection.CreateCommand();
command.CommandType = CommandTypes.StoredProcedure
command.CommandText = "some_stored_procedure"
// Pass in the parameters
However doing that causes Informix to throw a syntax error, so instead I have been forced to go with the:
var command = connection.CreateCommand();
command.CommandText = "execute procedure some_stored_procedure(?,?,?,?)";
// Pass in parameters
Which works but never passes back correct results, and if I try and make parameter 3 null it gives another syntax error. Am I missing something or is there a better way to call these stored procedures?
try parameterizing the parameters (you can use OdbcParameters if working with the odbcdriver) and then pass DbNull.Value where Null is required.
Try this:
var command = connection.CreateCommand();
command.CommandType = CommandTypes.Text;
command.CommandText = "call some_stored_procedure(?,?,?,?)";
command.Parameters.Add(param); //add all your parameters.
Format the query as follow:
strQuery = string.Format("EXECUTE PROCEDURE Cronos_UpdateStateLegacyProduct ({0})", oValidityProducts.PurchaseId);
OdbcConnection oConnection = new OdbcConnection(this.strConnectionString);
OdbcCommand oCommand = new OdbcCommand();
oCommand.CommandType = CommandType.StoredProcedure;
oCommand.CommandText = strQuery;
oCommand.Connection = oConnection;
oConnection.Open();
intResult = oCommand.ExecuteNonQuery();
Best Regards
In case you are using an ODBC connection, when using CommandType.StoredProcedure you must use a diferent syntax for the procedure's name. In your case:
CommandText = "{ CALL some_stored_procedure(?,?,?,?)}"
Check this link for more information: https://support.microsoft.com/en-us/kb/310130
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 long SQL query, it does some inserts, updates, then deletes. Each query uses the same 2 parameters. If I pass them in as SQL parameters from C#, it times out, after 20 mins. I just put the parameters into the command text, and it works. When I use it with the parameters it doesn't even show up in the profiler till it times out. Am I missing something?
SqlCommand comm = new SqlCommand(cmdText, conn);
comm.CommandTimeout = 5 * 60;
SqlParameter p = new SqlParameter("#key1", SqlDbType.Int);
p.Value = key1;
comm.Parameters.Add(p);
p = new SqlParameter("#key2", SqlDbType.Int);
p.Value = 1000000;
comm.Parameters.Add(p);
comm.ExecuteNonQuery();
If you take the parameter code out, and just to a replace on cmdText before executing the query it works. The query itself is a 300 lines or so. Each parameter gets used 51 times.
You may be missing the comm.Prepare() call before ExecuteNonQuery().
The key is in the SQL command, instead of saying "cmdText" post your SQL command.
EDIT: You are also not specifying a parameter direction in the code, it might be important.
Did you set the command type?
var command = new SqlCommand() { CommandType = CommandType.StoredProcedure };