-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parameter direction not supported in CommandType.Text #231
Comments
Can you give some ADO.NET code that illustrates the problem (particularly useful if you can contrast |
Sure, no prob. The code snippets below using EF Core should help.
Inspecting outParam.Value will show the integer value returned from the stored proc.
This gives the following MySql.Data.MySqlClient.MySqlException:
This is due to the following query being sent: When it should really be the following SQL: |
Sorry, I'm still not sure from that code snippet whether the problem is with this library, or with Pomelo EF Core's use of this library, or something else. Is there a way to reproduce this bug just by using ADO.NET methods? |
OK, I'll take EF Core out of this altogether and just focus on ADO.NET. I'm not sure I'd classify this a bug, but more of a limitation. Anyway, here is code for SQL Server and using (var db = new SqlConnection("Server=127.0.0.1"))
{
db.Open();
var outParam = new SqlParameter("@ParamOut", DbType.Int32)
{ Direction = ParameterDirection.Output };
var cmd = db.CreateCommand();
cmd.CommandText = "SET @ParamOut = 1";
cmd.Parameters.Add(outParam);
cmd.ExecuteNonQuery();
} Here is code for MySQL, a MySqlException will be raised.
using (var db = new MySqlConnection("server=127.0.0.1"))
{
db.Open();
var outParam = new MySqlParameter() { ParameterName = "@ParamOut",
DbType = DbType.Int32, Direction = ParameterDirection.Output };
var cmd = db.CreateCommand();
cmd.CommandText = "SET @ParamOut = 1";
cmd.Parameters.Add(outParam);
cmd.ExecuteNonQuery();
} The reason it fails is that If that's the case, an option would be to include code like below to alert the user that this won't work: if (parameterCollection.Any(p => p.Direction != ParameterDirection.Input))
throw new Exception("Parameters can only be input when using CommandType.Text"); |
Thank you; this is a very helpful example. I'd agree that this is more of a limitation (with MySQL itself). The "text" protocol doesn't provide any way of returning parameter values to the client; you have to explicitly FWIW, I get the same "invalid SQL" |
@bgrainger Thanks for confirming. Although, it appears that MySQL 5.5.3 has the ability to return the OUT parameter as an extra resultset. Is that something this library could take advantage of? |
This is the same as bug 75267 for Connector/NET. |
@bgrainger Nice find, although it appears Oracle is in no hurry to fix it! |
Any update on this? |
Are you referring to ADO.NET or EF Core? If the former, then you can use Using Stored Routines from Connector/NET to get the output values, otherwise no update. @bgrainger Would you be able to grab the OUT params of SP from the OK packet when UPDATE: Support for |
I am referring to EF Core. I have done already the ADO.NET solution. it works but it sucks. I have a huge proejct with dozens of stored procedures and I have to do the datareader stuff for every single field. Shame tha in year 2019 we are still forced to use ADO.NET |
|
It seems like we might be talking about two separate things here, though? A) executing (with This issue covers (A). (B) is already implemented (when |
@pantonis Try creating an extension method on the database facade to facilitate calling these procedures for you. The code below isn't tested, but should get you started. public static int CallStoredRoutine(this DatabaseFacade databaseFacade,
string routineName, params DbParameter[] parameters)
{
int rows;
var cmd = databaseFacade.GetDbConnection().CreateCommand();
cmd.CommandText = routineName;
cmd.Parameters.AddRange(parameters);
cmd.CommandType = CommandType.StoredProcedure;
databaseFacade.OpenConnection();
rows = cmd.ExecuteNonQuery();
databaseFacade.CloseConnection();
return rows;
} @bgrainger Apologies for conflating the issues. |
@mguinness Big mess here are the datareader reads and cast to model properties one by one. |
Using extension method you'll just read the |
@pantonis Can you give some example code? I'm not sure exactly what the problem is yet, and seeing the code might help me understand where MySqlConnector could be improved, or allow us to give some suggestions for improvement of your code. |
@mguiness I am not talking about the reading of output parameter but for the values returned from the SP.
|
All that code could be replaced with one line using Dapper:
I'd strongly suggest using a simple ORM library like Dapper to eliminate this repetitive boilerplate, while retaining very similar performance to the handwritten code above. |
You need to create a model and use |
@bgrainger I saw Dapper but I don't know if it is a good idea to mix 2 ORMS. I use EF Core for my business logic and I have been using it for years and I don't want to drop it for something I don't have experience with it. @mguinness I was doing this until I discovered that EF Core using with MySql does not support output params. This is why I switched to ADO.NET |
This probably isn't the right venue to get the answers you need. Ask a question on Stack Overflow with a Minimal, Reproducible Example and you'll likely get help for a solution that'll work for you. |
@mguinness It is not my intention to ask anything about dapper or ado.net. I initially wrote here to ask for the status of this issue that for the output parameters when using EF Core with MySql |
This repo (MySqlConnector) deals purely with ADO.NET; if you want an answer about EF Core, then https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql (or Stack Overflow) is the right place to raise the issue. (It's still not clear to me what this issue--ADO.NET output parameters for |
@bgrainger I thought that the problem exists in MySqlConnect (Parameter direction not supported in CommandType.Text). I saw this thread as open and you added it an an enhancment. |
Yes, that issue does exist. But AFAICT you're not using |
So EF Core team or Pomelo team have to change their code to use CommandType.Text |
No... it's just that |
Just to reiterate that your issue has nothing to do with MySqlConnector but rather EF Core. I quickly looked at the code in RelationalCommand.cs and they don't specify Therefore you have three situations when dealing with stored procedures in EF Core:
The one question I have regarding the MySQL text protocol is this - when using |
Prepared statements imply the binary protocol. (Unprepared, i.e., regular, statements use the text protocol.) Furthermore, I believe that |
Looking at the example in C API Prepared CALL Statement Support it calls a stored proc with question mark placeholders.
In the documentation for mysql_stmt_prepare() I see no reference to it being limited to stored procedures, but the string must consist of a single SQL statement.
Does that mean that |
It's not.
Yes, and it already does. (But only stored procedures have "OUT parameters". |
Back to the OP, there should be a way to make "OUT" parameters work with var outParam = new MySqlParameter() { ParameterName = "@ParamOut",
DbType = DbType.Int32, Direction = ParameterDirection.Output };
var cmd = db.CreateCommand();
cmd.CommandText = "SET @ParamOut = 1";
cmd.Parameters.Add(outParam);
cmd.ExecuteNonQuery(); This could be handled as follows: For each Then output the SQL without substituting parameter names with their values. Then append |
I don't think the extra code in the previous comment is worth implementing in this library; setting "out" parameters just isn't natively supported by MySQL and we shouldn't pretend that it is.
An exception with a link to documentation would help users in this situation. |
That was already implemented in #234.
Since it hasn't come up much, a link to documentation may be unnecessary. Closing this as an unsupported feature of the MySQL protocol; it doesn't have the capability to return named parameters from |
There's an issue when using parameter direction with Pomelo EF Core provider. Both
FromSql()
andExecuteSqlCommand()
can accept arrays of MySqlParameter (derived from DbParameter). If the Direction property is set to either InputOutput or Output it will not work as expected.This issue was already touched on in issue PomeloFoundation/Pomelo.EntityFrameworkCore.MySql#194 (comment).
This is due to the query being executed as
CommandType.Text
which uses TextCommandExecutor as opposed to the more advanced parameter support in StoredProcedureCommandExecutor.While I understand the limitations of
CommandType.Text
, it does mean there is a disparity between MySqlConnector and System.Data.SqlClient which does handle output parameters. It does this by using sp_executesql to run the query. For example:Is there a way to do something similar using prepared statements in MySQL? For example:
If this isn't feasible to do or a design decision is made to not support it then I think an exception should be thrown when Direction property is set to something other than ParameterDirection.Input as it won't work as expected.
Anyway this is something which would benefit from discussion and I'd like to get other people's viewpoints on this issue.
The text was updated successfully, but these errors were encountered: