| Bug #44349 | Connector/Net 5.2.5 ignores parameter names | ||
|---|---|---|---|
| Submitted: | 17 Apr 2009 20:07 | Modified: | 30 Apr 2009 13:35 |
| Reporter: | Julian Beckensall | Email Updates: | |
| Status: | Not a Bug | Impact on me: | |
| Category: | Connector / NET | Severity: | S2 (Serious) |
| Version: | 5.2.5 | OS: | Any |
| Assigned to: | Reggie Burnett | CPU Architecture: | Any |
| Tags: | connector, parameter names | ||
[17 Apr 2009 20:07]
Julian Beckensall
[20 Apr 2009 8:44]
Tonci Grgin
Hi Julian and thanks for your report. I can't gather much about the problem from your words so if you can come up with simple test case (incl. DDL/DML) that I can load into VS2005/8 I will take a look.
[20 Apr 2009 10:39]
Julian Beckensall
Hi Tonci. Sorry - should have supplied this originally.
Stored proc: -
----------------------------------------
DELIMITER $$
DROP PROCEDURE IF EXISTS `XXXXXX`.`spParamTest` $$
CREATE PROCEDURE `XXXXXX`.`spParamTest` (p_1 varchar(5), p_2 varchar(5))
BEGIN
select p_1 as P1, p_2 as P2;
END $$
DELIMITER ;
----------------------------------------
VS2005 C# Code: -
----------------------------------------
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using MySql.Data.MySqlClient; // Version 5.2.5.0 (Runtime = v2.0.50727)
namespace paramTest
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Connection String
// Need "Use Procedure Bodies =false" as I don't have access to the "procs" table
// Server is a remote, Linux server
// ASP.Net code running on my XP PC but behaves the same on Win2003 server
string connstr = "Database=XXXXX;Data Source=###.###.###.###;User Id=XXXXX;Password=XXXXX; Use Procedure Bodies =false;";
// Open connection
MySqlConnection conn = new MySqlConnection(connstr);
conn.Open();
MySqlCommand cmd = new MySqlCommand("spParamTest", conn);
cmd.CommandType = CommandType.StoredProcedure;
// Add Params in the 'wrong' order
cmd.Parameters.AddWithValue("p_2", "World");
cmd.Parameters.AddWithValue("p_1", "Hello");
// Get Adapter
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
// Create + Populate Dataset
DataSet dataset = new DataSet();
adapter.Fill(dataset);
// Show return values - should be "P1: Hello", "P2: World"
Response.Write("P1: " + dataset.Tables[0].Rows[0]["P1"].ToString());
Response.Write("<br/>");
Response.Write("P2: " + dataset.Tables[0].Rows[0]["P2"].ToString());
// Tidy up
conn.Close();
conn = null;
dataset = null;
}
}
}
[20 Apr 2009 13:47]
Tonci Grgin
Julian, your parameters have no sense of direction :-) Have you tried defining:
o in SP: IN p_1 varchar(5), IN p_2 varchar(5)
o in C#: cmd.Parameters[0].Direction = ParameterDirection.Input;
cmd.Parameters[1].Direction = ParameterDirection.Input;
Does the test work if all is defined like this? How does, if you can test it, "Use Procedure Bodies = true" change things?
[20 Apr 2009 13:58]
Tonci Grgin
This works as expected:
cmdCreateTable.CommandText = ("CREATE PROCEDURE `SP_BUG44349`(" + "\n" +
"IN p_1 VARCHAR(5), \n" +
"IN p_2 VARCHAR(5) \n" +
") \n" +
"BEGIN SELECT p_1 AS P1, p_2 AS P2; END\n");
try
{
cmdCreateTable.ExecuteNonQuery();
MySqlCommand cmd = new MySqlCommand("SP_BUG44349", conn);
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("?p_1", ("Hello"));
cmd.Parameters[0].DbType = DbType.AnsiString;
cmd.Parameters[0].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("?p_2", ("world"));
cmd.Parameters[1].DbType = DbType.AnsiString;
cmd.Parameters[1].Direction = ParameterDirection.Input;
MySqlDataAdapter adapter = new MySqlDataAdapter(cmd);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
Console.WriteLine("P1: " + dataset.Tables[0].Rows[0]["P1"].ToString());
Console.WriteLine("P2: " + dataset.Tables[0].Rows[0]["P2"].ToString());
dataset = null;
against remote MySQL server 5.1.31 on OpenSolaris host. .NET FW used is 3.5.
[20 Apr 2009 14:24]
Julian Beckensall
Hi again Tonci.
The code you supplied does work, but only because you create the parameters in the correct order in the ASP code.
If I change your code to this (adding p_2, THEN p_1), it doesn't: -
cmd.Parameters.AddWithValue("?p_2", ("world"));
cmd.Parameters[0].DbType = DbType.AnsiString;
cmd.Parameters[0].Direction = ParameterDirection.Input;
cmd.Parameters.AddWithValue("?p_1", ("Hello"));
cmd.Parameters[1].DbType = DbType.AnsiString;
cmd.Parameters[1].Direction = ParameterDirection.Input;
In other words, it seems to ignore the parameter names and goes by the order in which they were added to the Command object.
I have tried to connect without the "Use Procedure Bodies = false", but I get this error: "SELECT command denied to user 'XXXXX'@'XXXXX.com' for table 'proc'". As this database is controlled by the ISP, I don't seem to have any choice but to use it.
Thanks for your help.
Julian.
[20 Apr 2009 14:51]
Tonci Grgin
Julian, you are right. Verified as described with test case already pasted. Replacing
cmd.Parameters.AddWithValue("?p_1", ("Hello"));
and
cmd.Parameters.AddWithValue("?p_2", ("Hello"));
shows the problem:
[20.4.2009 16:48:48] - Executing command QUERY with text ='call SP_BUG44349 ('world', 'Hello')'
P1: world
P2: Hello
[30 Apr 2009 13:35]
Reggie Burnett
This is expected behavior when you use 'use procedure bodies=false'. The reason is that when we don't have access to the procedure bodies the connector cannot determine what the parameters for a proc are. In that case, the connector has no choice but to use the parameters in the order they are added to the command. this is actually a fairly nice optimization. As long as you add the parameters in the right order you avoid a round trip to the server to get parameter names which speeds things up.
