C# MySql Parameterized Query makes longs into null - c#

The code is based on https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html
public void TableTest(string connectionString)
{
string sqlToCreateTable = #"CREATE TABLE IF NOT EXISTS my_table
(auction_key BIGINT NOT NULL, auction_owner VARCHAR(25), first_seen BIGINT,
PRIMARY KEY(auction_key))";
string sqlInsertOrUpdateAuction = "INSERT INTO my_table (auction_key) VALUES (#my_auc_id); ";
using (MySqlConnection dbConnection = new MySqlConnection(connectionString))
{
dbConnection.Open();
// is the table in the database?
MySqlCommand cmd = new MySqlCommand(sqlToCreateTable, dbConnection);
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.ExecuteNonQuery();
}
}
The error is that 123456 is seen as null.
Message=Column 'auction_key' cannot be null
I tried changing the "strict" setting in my.ini and it makes no difference.
Help please.

Well, you add the parameter to the command and then instantiate a new command:
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
If you do that, the command will no longer have the value for the #my_auc_id. Try switching those two lines:
cmd = new MySqlCommand(sqlInsertOrUpdateAuction, dbConnection);
cmd.Parameters.AddWithValue("#my_auc_id", 123456);
Hope this helps.

You could alleviate your issue, by simply doing the following:
using(var connection = new MySqlConnection(dbConnection))
{
connection.Open();
using(var command = new MySqlCommand(createTableQuery, connection))
{
command.ExecuteNonQuery();
}
using(var command = new MySqlCommand(insertOrUpdate, connection))
{
command.Parameters.Add("..", SqlDbType = SqlDbType.Int).Value = 123456;
command.ExecuteNonQuery();
}
}
Keep in mind that ExecuteNonQuery will return a zero or one, if it successfully worked. Also you may want to manually specify the SqlDbType. To avoid SQL inferring incorrectly. Also, this will correctly scope your MySqlCommand, so you can correctly utilize for the queries.
And according to the documentation, it does implement the IDisposable to utilize the using block. This ensures you instantiate your MySqlCommand again.

Related

ODBC Command Procedure Function Expects Parameters

The stored procedure in SQL works perfectly with the desired result.
ALTER PROCEDURE [dbo].[My_StoredProc]
(#autoidx int,
#r varchar(max) OUTPUT)
--with encryption
AS
BEGIN
-- ... some code here ...
END
Trying to call the stored procedure in VS 2019 using ODBC command but I get getting an error :
Procedure or function My_StoredProc expects parameter #autoidx, which was not supplied.
My code:
string connectionString = String.Format("DSN={0};uid=my_user;pwd=my_pwd", toolStripComboBoxDSN.Text);
// OdbcCommand DbCommand = new OdbcCommand("My_StoredProc", DbConnection);
// DbCommand.CommandType = CommandType.StoredProcedure;
//DbCommand.Parameters.AddWithValue("#autoidx", this.AutoIndex); //this.AutoIndex has value
//DbCommand.Parameters.Add("#r", OdbcType.VarChar,500);
//DbCommand.Parameters["#r"].Direction = ParameterDirection.Output;
//DbConnection.Open();
//DbCommand.ExecuteNonQuery();
//string s = (string)DbCommand.Parameters["#r"].Value;
//Code below is working. With a major change in CommandType
OdbcCommand DbCommand = new OdbcCommand(" EXEC dbo.My_StoredProc #autoidx=? ", DbConnection);
DbCommand.CommandType = CommandType.Text;
DbCommand.Parameters.Add("?", OdbcType.Int).Value = this.AutoIndex;
DbConnection.Open();
var s = DbCommand.ExecuteScalar();
I had one opinion:
1.- Try to change this
DbCommand.Parameters.AddWithValue("#autoidx", this.AutoIndex);
for this:
DbCommand.Parameters.Add("#autoidx", SqlDbType.Int);
DbCommand.Parameters["#autoidx"].Value = this.AutoIndex;
2.- Check you DbConnection, sometimes this contain other database for example db_developer instead of db_production.
Try to use the System.Data.SqlClient native SQL client to SQL Server, and use proper using blocks and proper parameter definition - something like this:
// standard SQL Client connection string
string connectionString = "......";
// define connection and command in proper "usinh" blocks
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("dbo.My_StoredProc", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// define parameters properly
cmd.Parameters.Add("#autoidx", SqlDbType.Int);
cmd.Parameters.Add("#r", SqlDbType.VarChar, -1).Direction = ParameterDirection.Output;
// set values to parametesr
cmd.Parameters["#autoidx"] = this.AutoIndex;
// open connection, execute procedure, close connection
conn.Open();
int rowsAffected = cmd.ExecuteNonQuery();
string s = cmd.Parameters["#r"].Value?.ToString();
conn.Close();
}

SQLCLR stored procedures with input parameter

I am quite new to SQLCLR stored procedures. In my example I have two stored procedures, one without a parameter and one with a input parameter. Both target the same tables.
The one without the parameter is working fine and returns all rows in the result. But the one with an input parameter targeting the same tables is not returning any rows even though I am not receiving any errors. The input parameter in the .NET code is set as SqlString and in the database is NVARCHAR(50).
This is how my C# code looks:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineSqlStoredProcedure (SqlString strAirline)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID WHERE AirlineName = '#strAirline' ORDER BY dbo.tblAircraft.AircraftUnits DESC";
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
cmd.Parameters.Add(paramAge);
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
[Microsoft.SqlServer.Server.SqlProcedure]
public static void AirlineAircraftStoredProcedure()
{
//It returns rows from Roles table
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Context Connection=true";
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT dbo.tblAirline.AirlineName, dbo.tblAircraft.AircraftUnits, dbo.tblAircraft.Manufacturer, dbo.tblAircraft.AircraftModel FROM dbo.tblAircraft INNER JOIN dbo.tblAirline ON dbo.tblAircraft.AirlineID = dbo.tblAirline.AirlineID ORDER BY dbo.tblAircraft.AircraftUnits DESC";
conn.Open();
SqlDataReader sqldr = cmd.ExecuteReader();
SqlContext.Pipe.Send(sqldr);
sqldr.Close();
conn.Close();
}
}
And when I execute the stored procedure I get empty rows:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineSqlStoredProcedure]
#strAirline = N'American Airlines'
SELECT #return_value as 'Return Value'
GO
(0 row(s) affected)
(1 row(s) affected)
Also, for the input parameter I put an N before the string.
When running the stored procedure AirlineAircraftStoredProcedure targeting the same tables, I am getting all the rows back:
USE [TravelSight]
GO
DECLARE #return_value Int
EXEC #return_value = [dbo].[AirlineAircraftStoredProcedure]
SELECT #return_value as 'Return Value'
GO
(8 row(s) affected)
(1 row(s) affected)
What have I done wrong here?
Two (maybe 3) problems:
paramAge.Value = strAirline; should be:
paramAge.Value = strAirline.Value;
Notice the use of the .Value property.
WHERE AirlineName = '#strAirline' (within cmd.CommandText = "... ) should be:
WHERE AirlineName = #strAirline
Notice that the single-quotes were removed in the query text. You only use single-quotes for literals and not parameters / variables.
Replace the following 5 lines:
SqlParameter paramAge = new SqlParameter();
paramAge.Value = strAirline;
paramAge.Direction = ParameterDirection.Input;
paramAge.SqlDbType = SqlDbType.NVarChar;
paramAge.ParameterName = "#strAirline";
with:
SqlParameter paramAge = new SqlParameter("#strAirline", SqlDbType.NVarChar, 50);
paramAge.Direction = ParameterDirection.Input; // optional as it is the default
paramAge.Value = strAirline.Value;
Please note that the "size" parameter was set in the call to new SqlParameter(). It is important to always specify max string lengths.
With the technical problem out of the way, there are two larger issues to address:
Why is this being done in SQLCLR in the first place? Nothing specific to .NET is being done. Based solely on the code posted in the Question, this would be much better off as a regular T-SQL Stored Procedure.
If it must remain in SQLCLR, then you really need to wrap the disposable objects in using() constructs, namely: SqlConnection, SqlCommand, and SqlDataReader. For example:
using (SqlConnection conn = new SqlConnection("Context Connection=true"))
{
using (SqlCommand cmd = conn.CreateCommand())
{
...
}
}
and then you do not need the following two lines:
sqldr.Close();
conn.Close();
as they will be called implicitly by the call to each of their Dispose() methods.

how to fetch data using this coding

using this coding,while i give fruitId ,i need to retrieve fruitname,using this it shows some error..any one help...
string constring = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("savefruit11", con))
{
con.Open();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#FruitsId", int.Parse(TextBox3.Text.Trim()));
cmd.Parameters.Add("#Fruitsname", SqlDbType.VarChar, 50);
cmd.Parameters["#Fruitsname"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
con.Close();
TextBox4.Text = "Fruit Name:"+cmd.Parameters["#FruitName"].Value.ToString();
}
}
Store procedure for the above code.
use[FruitsDB]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[savefruit11]
#FruitId INT,
#FruitName VARCHAR(50) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SELECT #FruitName = Fruitsname
FROM Fruits1
WHERE FruitsId = #FruitId
END
cmd.Parameters.Add("#Fruitsname", SqlDbType.VarChar, 50);
cmd.Parameters["#Fruitsname"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
con.Close();
TextBox4.Text = "Fruit Name:"+cmd.Parameters["#FruitName"].Value.ToString();
Your parameter is called #Fruitsname, but you get it back with #FruitName. You have an additional s in the first version. Make them consistent by changing the first #FruitsName to #FruitName which will match what you have in the stored procedure.
Or, as Henk suggested in the comments create a const string to contain your parameter name so that it is consistent across all usages.
Use cmd.ExecuteQuery or cmd.ExecuteScalar
//To Execute SELECT Statement
ExecuteQuery()
//To Execute Other Than Select Statement(means to Execute INSERT/UPDATE/DELETE)
ExecuteNonQuery()
with your udpate
s is missing in parameter name in stored procedure
Use the following example way
using (SqlConnection connection = new SqlConnection())
{
string connectionStringName = this.DataWorkspace.AdventureWorksData.Details.Name;
connection.ConnectionString =
ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
string procedure = "HumanResources.uspUpdateEmployeePersonalInfo";
using (SqlCommand command = new SqlCommand(procedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(
new SqlParameter("#EmployeeID", entity.EmployeeID));
command.Parameters.Add(
new SqlParameter("#NationalIDNumber", entity.NationalIDNumber));
command.Parameters.Add(
new SqlParameter("#BirthDate", entity.BirthDate));
command.Parameters.Add(
new SqlParameter("#MaritalStatus", entity.MaritalStatus));
command.Parameters.Add(
new SqlParameter("#Gender", entity.Gender));
connection.Open();
command.ExecuteNonQuery();
}
}
reference from MSDN
http://msdn.microsoft.com/en-us/library/jj635144.aspx

Sql transaction c# - exits try when ExecuteNonQuery() is run

I'm trying to implement an sql transaction, however, i've run into a bit of bother. I have a simple database with has three tables. Users, Post and Comments. I wish to implement a delete button that will delete a user from the Users table. The initial problem I had was that I needed to remove the users FK from both the post and comment table, then remove the user from the User table. I looked online and somebody had suggested using transaction for multiple server calls. Here is my code:
public void DeleteUser(int UserId)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlTransaction sqlTran = con.BeginTransaction();
try
{
using (SqlCommand command = new SqlCommand("DELETE FROM Comment WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
using (SqlCommand command = new SqlCommand("DELETE FROM Post WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
using (SqlCommand command = new SqlCommand("DELETE FROM Users WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
sqlTran.Commit();
}
catch
{
sqlTran.Rollback();
}
}
}
The problem I have is that when the DeleteUser method is run, the program gets as far as the command.ExecutyNonQuery in the first using block, then jumps to the catch. Thus rolling back the changes. There isn't any error codes displayed, so i'm not sure what is going wrong.
Any help in this matter would be greatly appreciated.
You're missing command.Transaction = sqlTran;.
DO NOT USE try {} catch {}. Use at least try {} catch (Exception ex) {} -> this will give you enough information to solve the problem on your own.

Getting ORA-01036 error when using output parameter in C#

I am having a problem with an Output parameter in C#/Oracle. I have isolated the code that I need to get working.
This is part of a much larger SQL statement, so do not worry too much if it doesn't make sense. In short I need to copy a row, give it a new ID and return that new ID. I tried using "RETURNING" which did not work. I see no reason why the code below should not work, but I'm getting an "ORA-01036: illegal variable name/number" error. Can anyone see what I'm doing wrong?
using (OracleConnection conn = new OracleConnection(connString))
{
// Open connection and create command.
conn.Open();
using (OracleCommand cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("outValue", OracleType.Int32).Direction = ParameterDirection.Output;
cmd.CommandText = "SELECT seq.nextval INTO :outValue FROM dual";
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
// This is just to see the exception when it fails.
}
}
}
The name of the parameter doesn't match.
cmd.Parameters.Add(":outValue", OracleType.Int32).Direction.......;
^
I have also seen this variation on the query syntax
"BEGIN SELECT seq.nextval INTO :outValue FROM dual END;"
You are using named parameters. Try setting:
cmd.BindByName = true;
Have you tried 'returning' keyword like this?
This code works for me.
using (OracleConnection conn = new OracleConnection(connString))
{
// Open connection and create command.
conn.Open();
using (OracleCommand cmd = new OracleCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("outValue", OracleType.Int32).Direction = ParameterDirection.Output;
cmd.CommandText = "insert into table (id, value) values (seq.nextval, 'value') returning id into :outValue";
cmd.ExecuteNonQuery();
}
}

Categories