MySQL .Net Connector Issue Executing Routine - c#

I'm having an issue getting my code to execute a MySQL routine.
Keeps popping error:
Procedure or function 'ShortenedURLS' cannot be found in database 'Get'.
Routine
DELIMITER $$
USE `o7thurlshortner`$$
DROP PROCEDURE IF EXISTS `Get.ShortenedURLS`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `Get.ShortenedURLS`(IN `ID` BIGINT)
NO SQL
SELECT `ShortID`, `ShortCode`, `URL`, `ClickThroughs`
FROM `Shortener`
WHERE `AccountID` = ID$$
DELIMITER ;
Code - Accessing and running the routine
internal DbDataReader GetResults()
{
try
{
// check for parameters
if (AreParams())
{
PrepareParams(_Cmd);
}
// set our connection
_Cmd.Connection = _Conn;
// set the type of query to run
_Cmd.CommandType = _QT;
// set the actual query to run
_Cmd.CommandText = _Qry;
// open the connection
_Cmd.Connection.Open();
// prepare the command with any parameters that may have gotten added
_Cmd.Prepare();
// Execute the SqlDataReader, and set the connection to close once returned
_Rdr = _Cmd.ExecuteReader(CommandBehavior.CloseConnection);
// clear out any parameters
_Cmd.Parameters.Clear();
// return our reader object
return (!_Rdr.HasRows) ? null : _Rdr;
}
catch (DbException SqlEx)
{
_Msg += "Acccess.GetResults SqlException: " + SqlEx.Message;
ErrorReporting.WriteEm.WriteItem(SqlEx, "o7th.Class.Library.Data.MySql.Access.GetResults", _Msg);
return null;
}
catch (Exception ex)
{
_Msg += "Acccess.GetResults Exception: " + ex.Message;
ErrorReporting.WriteEm.WriteItem(ex, "o7th.Class.Library.Data.MySql.Access.GetResults", _Msg);
return null;
}
}
Code - to fire it off
IList<Typing> _T = Wrapper.GetResults<Typing>("Get.ShortenedURLS",
System.Data.CommandType.StoredProcedure,
new string[] { "?ID" },
new object[] { 1 },
new MySqlDbType[] { MySqlDbType.Int32 },
false);
Update
Verified this does work properly once I fireoff a routine without a . in it.
How can I get this to work if my routines do have .'s, I cannot simply re-write existing procedures in a production database tied to a high traffic website...

In order to call you stored procedure you do have to wrap the name of it in backticks since it contains the special character .
However, there is a bug in the mysql connector code that is causing it to escape it again. When you specify
cmd.CommandType = CommandType.StoredProcedure;
The code branches during execute reader as you can see below...
if (statement == null || !statement.IsPrepared)
{
if (CommandType == CommandType.StoredProcedure)
statement = new StoredProcedure(this, sql);
else
statement = new PreparableStatement(this, sql);
}
// stored procs are the only statement type that need do anything during resolve
statement.Resolve(false); // the problem occurs here
part of what Resolve does is fix the procedure name..
//StoredProcedure.cs line 104-112
private string FixProcedureName(string name)
{
string[] parts = name.Split('.');
for (int i = 0; i < parts.Length; i++)
if (!parts[i].StartsWith("`", StringComparison.Ordinal))
parts[i] = String.Format("`{0}`", parts[i]);
if (parts.Length == 1) return parts[0];
return String.Format("{0}.{1}", parts[0], parts[1]);
}
As you can see here, anytime the stored procedure name has a . in it, the name of the stored procedure is broken up into parts and escaped individually, and this is causing your code to not be able to call your stored procedure.
So your only options to fix this are..
1) Open a bug with oracle to fix the provider (assuming there is not one already open)
2) Change the name of your stored procedure to not use a .
3) Download the code for the provider, fix it, recompile
4) Find another connector

Related

How execute a stored procedure from the web method?

I want to execute a stored procedure inside a Web Method. It is a select statement in the stored procedure. I tried with the following code. However, the result not successful. The result should return 1 but it is always returning -1. Does anyone have any idea? Please help.
Here is the web service .asmx code:
public class retrieveLoan : System.Web.Services.WebService
{
string constring = "Data Source=DIT-NB1260382;Initial Catalog=Experiment;Integrated Security=True";
SqlConnection myConn;
[WebMethod(Description="Simple Example")]
public int GetResult(int id, int age)
{
Int32 numberofRecords = 0;
System.Data.DataSet workDS = new System.Data.DataSet();
SqlCommand objCommand = default(SqlCommand);
//Create a command object
objCommand = new SqlCommand();
//prepare the command for retreiving
objCommand.CommandType = System.Data.CommandType.StoredProcedure;
objCommand.CommandText = "myprocedure2";
//open the connection
myConn = new SqlConnection(constring);
myConn.Open();
objCommand.Connection = myConn;
try
{
numberofRecords = (Int32)objCommand.ExecuteScalar();
return numberofRecords;
}
catch (Exception)
{
return -1;
}
finally
{
myConn.Close();
}
}
}
and my store procedure:
ALTER PROCEDURE [dbo].[myprocedure2]
(
#puserid int,
#page int
)
AS
BEGIN
select * from userdet where userid = #puserid and age = #page
END
I believe that executing this stored procedure without parameters would return an exception.
First of all, for you to see the Exception, in the catch declaration, you should try and declare the Exception explicitly, like this:
try
{
numberofRecords = (Int32)objCommand.ExecuteScalar();
return numberofRecords;
}
catch (Exception ex)
{
//here you can enter into debug mode and see the exception "ex"
return -1;
}
finally
{
myConn.Close();
}
When you see the exception, you can quickly solve the problem.
Next, you should add the parameters as NULL into your stored procedure (so they can accept null values), OR, if you do not, you must add these parameter in C# code, and send them some values.
Also, i would like to point the fact that if you want to retrieve a COUNT, you should modify your stored procedure as following:
ALTER PROCEDURE [dbo].[myprocedure2] ( #puserid int, #page int )
AS
BEGIN
select COUNT(userid) from userdet where userid = #puserid and age = #page
END
Hope this solves your issues here.
You're not providing a lot of info, so hard to answer, but here's a way forward:
Change catch (Exception) into catch (Exception ex), then see what that exception contains, either by returning it, or by analyzing it in debug mode.
If you publish your project in debug mode, you can connect to it and debug it using Tools > Attach to Process and connect to the process called w3wp.exe (if there are more than one of them, look for the one with the correct version of .Net under the Type-column).
Your query is "select * from userdet". What ExecuteScalar() does is pick the first cell value. Now you are type casting this to int. if your first cell value is a string type or some other type. you will definitely receive a error. And that will return -1. Please define the column name in your select query or count like this "select count(*) from userdet". Check ur query.

Firebird: Alter table and create stored procedure from out C#

I'm trying to create a stored procedure from out C# into Firebird 2.1.
The code is:
String sql = #"EXECUTE BLOCK AS BEGIN " +
"ALTER TABLE EXAMPLE ALTER FIELD1 TYPE Char(50); " +
"SET TERM ^ ; CREATE PROCEDURE name ( input_parameter_name < datatype>, ... )" +
"RETURNS ( output_parameter_name < datatype>, ... ) AS DECLARE VARIABLE variable_name < datatype>;" +
"BEGIN /* write your code here */ END^ SET TERM ; ^" +
" END";
public int Execute(string sql)
{
int result = 0;
if (this.OpenConnection() == true)
{
FbTransaction transaction = Fbconnection.BeginTransaction();
try
{
FbCommand command = new FbCommand(sql, Fbconnection, transaction);
int rc = command.ExecuteNonQuery();
result = rc;
transaction.Commit();
}
catch (Exception e)
{
globals.logfile.log(e.ToString());
globals.logfile.flush();
result = 0;
}
finally
{
this.CloseConnection();
}
}
return result;
}
The error message given is:
FirebirdSql.Data.FirebirdClient.FbException (0x80004005):
Dynamic SQL Error SQL error code = -104 Token unknown - line 1, column 24 ALTER
Must be something small, but I can't get it.
DDL is not allowed in PSQL (stored procedures, triggers, execute block), so executing an ALTER TABLE like this is rejected.
Also SET TERM is not part of the Firebird statement syntax. It is specific to query tools like isql and FlameRobin, as they use statement terminators like ; to know when they end of a statement is reached and can be sent to the server. When executing PSQL blocks those tools need to watch for a different statement terminator to prevent them from sending incomplete statements to the server. In the actual Firebird statement syntax ; is only part of PSQL blocks.
You will need to execute the ALTER TABLE and the CREATE PROCEDURE separately without an EXECUTE BLOCK.

sqlCommand and programatically retrieving and setting parameters of stored procedures

I'm new to .NET but need to swim in the deep end for a bit. I've been tasked with expanding an existing unit test that currently just attempts to receive the columns for all stored procedures (as a means of testing the integrity of the db connections and the schema therein). The goal is to retrieve the parameters for all stored procedures and attempt to run them with null values, testing to verify that no record sets are returned. I've been beating my head against the wall trying to get up to speed with ADO.NET but cannot for the life of me figure out how to do this. This is as far as I've gotten (taken somewhat out of context). The test complains that no parameter is being passed in, but I thought I was setting the existing parameter set to null and simply passing it back.
// bind our sql schema gridview
foreach (SqlSchemaItem item in items)
{
// pull a connection
using (var sqlConnection = new SqlConnection(connectionString))
{
// open connection
sqlConnection.Open();
// get schema
try
{
/*
* Part 1 - test that the schema is ok...
*/
var sqlCommand = new SqlCommand(item.ObjectName, sqlConnection);
sqlCommand.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(sqlCommand);
sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly);
// success to console
Console.WriteLine(item.ObjectName + " is ok.");
/*
* Part 2 - test that the stored procedure does not return any data.
*/
// set all the parameters to NULL
foreach (SqlParameter parameter in sqlCommand.Parameters)
{
if (parameter.Direction == ParameterDirection.Input || parameter.Direction == ParameterDirection.InputOutput)
{
parameter.Value = null;
Console.WriteLine("Parameter {0} set to null", parameter.ParameterName, parameter.Value);
}
}
var temp = sqlCommand.ExecuteReader(CommandBehavior.SingleResult);
if (temp.HasRows) {
Console.WriteLine(string.Format("A record was returned in {0} with value {0}", temp.GetName(0), temp.GetString(0)));
}
else {
Console.WriteLine("No result was returned");
}
Console.WriteLine(" ");
}
catch ...
finally ...
etc.
Use DBNull.Value instead of null.

"connection has been disabled" error message when quickly creating/deleting databases

Introduction
I'm writing a web application (C#/ASP.NET MVC 3, .NET Framework 4, MS SQL Server 2008, System.Data.ODBC for database connections) and I'm having quite some issues regarding database creation/deletion.
I have a requirement that application should be able to create and delete databases.
Problem
Application fails stress testing for that function. More specifically, if client starts to quickly create, delete, create again a database with the same name then eventually (~on 5th request) server code throws ODBCException 'Connection has been disabled.'. This behavior is observed on all machines that test has been performed on - the exact failing request may be not 5th but somewhere around that value.
Research
Googling on exception gave very low output - the exception seems very generic one and no analogue issues found. One of suggestions I've found was that my development Windows 7 might not be able to handle numerous simultaneous connections as it's not Server OS. I've tried installing our app on Windows 2008 Server - almost no change in behavior, just a bit more requests processed before exception occurs.
Code and additional comments on implementation
Databases are created using stored procedure like this:
CREATE PROCEDURE [dbo].[sp_DBCreate]
...
#databasename nvarchar(124) -- 124 is max length of database file names
AS
DECLARE #sql nvarchar(150);
BEGIN
...
-- Create a new database
SET #sql = N'CREATE DATABASE ' + quotename(#databasename, '[');
EXEC(#sql);
IF ##ERROR <> 0
RETURN -2;
...
RETURN 0;
END
Databases are deleted using the following SP:
CREATE PROCEDURE [dbo].[sp_DomainDelete]
...
#databasename nvarchar(124) -- 124 is max length of database file names
AS
DECLARE #sql nvarchar(200);
BEGIN
...
-- check if database exists
IF EXISTS(SELECT * FROM [sys].[databases] WHERE [name] = #databasename)
BEGIN
-- drop all active connections
SET #sql = N'ALTER DATABASE' + quotename(#databasename, '[') + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE';
EXEC(#sql);
-- Delete database
SET #sql = N'DROP DATABASE ' + quotename(#databasename, '[');
EXEC(#sql);
IF ##ERROR <> 0
RETURN -1; --error deleting database
END
--ELSE database does not exist. consider it deleted.
RETURN 0;
END
In both SPs I've skipped less relevant parts like sanity checks.
I'm not using any ORMs, all SPs are called from code by using OdbcCommand instances. New OdbcConnection is created for each function call.
I sincerely hope someone might give me clue to the problem.
UPD: The exactly same problem occurs if we just rapidly create a bunch of databases. Thanks to everyone for suggestions on database delete code, but I'd prefer to have a solution or at least a hint for more general problem - the one which occurs even without deleting DBs at all.
UPD2: The following code is used for SP calls:
public static int ExecuteNonQuery(string sql, params object[] parameters)
{
try
{
var command = new OdbcCommand();
Prepare(command, new OdbcConnection( GetConnectionString() /*irrelevant*/), null, CommandType.Text, sql,
parameters == null ?
new List<OdbcParameter>().ToArray() :
parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray());
return command.ExecuteNonQuery();
}
catch (OdbcException ex)
{
// Logging here
throw;
}
}
public static void Prepare(
OdbcCommand command,
OdbcConnection connection,
OdbcTransaction transaction,
CommandType commandType,
string commandText,
params OdbcParameter[] commandParameters)
{
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
command.Connection = connection;
command.CommandText = commandText;
if (transaction != null)
{
command.Transaction = transaction;
}
command.CommandType = commandType;
if (commandParameters != null)
{
command.Parameters.AddRange(
commandParameters.Select(p => p.Value==null &&
p.Direction == ParameterDirection.Input ?
new OdbcParameter(p.ParameterName, DBNull.Value) : p).ToArray());
}
}
Sample connection string:
Driver={SQL Server}; Server=LOCALHOST;Uid=sa;Pwd=<password here>;
Okay. There may be issues of scope for OdbcConnection but also you don't appear to be closing connections after you've finished with them. This may mean that you're reliant on the pool manager to close off unused connections and return them to the pool as they timeout. The using block will automatically close and dispose of the connection when finished, allowing it to be returned to the connection pool.
Try this code:
public static int ExecuteNonQuery(string sql, params object[] parameters)
{
int result = 0;
try
{
var command = new OdbcCommand();
using (OdbcConnection connection = new OdbcConnection(GetConnectionString() /*irrelevant*/))
{
connection.Open();
Prepare(command, connection, null, CommandType.Text, sql,
parameters == null ?
new List<OdbcParameter>().ToArray() :
parameters.Select(p => p is OdbcParameter ? (OdbcParameter)p : new OdbcParameter(string.Empty, p)).ToArray());
result = command.ExecuteNonQuery();
}
}
catch (OdbcException ex)
{
// Logging here
throw;
}
return result;
}

How to define terminating character for sql statement for DB2 using .net

I am tring to execute the following
public void ExecuteNonQuery(string script) {
try {
int returnCode;
var builder = new DB2ConnectionStringBuilder {
UserID = Context.Parameters["USERID"],
Password =Context.Parameters["PASSWORD"],
Database = Context.Parameters["DATABASE"],
CurrentSchema = Context.Parameters["CURRENTSCHEMA"]
};
using (var connection = new DB2Connection(builder.ConnectionString)) {
using (var command = new DB2Command(script, connection)
) {
command.CommandType = CommandType.Text;
connection.Open();
returnCode = command.ExecuteNonQuery();
File.WriteAllText(Context.Parameters["LOGFILE"], "Return Code -1 Successful : " + returnCode);
}
}
}
catch (Exception ex) {
Trace.WriteLine(ex.StackTrace);
throw ex;
}
}
I am calling a script that has multiple statements ending in ;'s and at the end of the file it contains an # symbol. On a db2 command line I could use the db2 -td# -f . I would like to know how to define the # symbol as the statement terminator so I could execute the script from csharp.
Here is example sql file :
DROP PROCEDURE fred#
CREATE PROCEDURE fred ( IN name, IN id )
specific fred
language sql
b1: begin
update thetable
set thename = name
where table_id = id;
end: b1
#
grant execute on procedure inst.fred to user dbuser#
I am not sure how we can define delimiters. But, you could try to split the whole text into individual statements in C# and then execute one statement after the other. Would that work for you?
That's an old question, but I had similar problem and here is the solution:
--#SET TERMINATOR #
create or replace procedure test
begin
declare line varchar(100);
set line = 'hello db2 world!';
call dmbs_output.put_line(line);
end#
and then just:
$ db2 -f script.sql
and it will work fine.

Categories

Resources