ExecuteScalar returns value is not suitable - c#

I use Enterprise Library and I have one problem:
string sql = "
UPDATE StackOverflow SET UserName = #UserName
WHERE Id = #Id
";
DbCommand cmd = base.Database.GetSqlStringCommand(sql);
base.Database.AddInParameter(cmd, "Id", DbType.Int32, StackOverflow.Id);
base.Database.AddInParameter(cmd, "UserName", DbType.Int32, StackOverflow.UserName);
int val = Convert.ToInt32(base.Database.ExecuteScalar(cmd));
Convert.ToInt32(base.Database.ExecuteScalar(cmd)) //returns 0.
I've read this article http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
The article says:
The function returns the new Identity column value if a new row was inserted, 0 on failure.
but I did not insert into that table - I only want to update and return updated row Id.

You should use ExecuteNonQuery in your case.
ExecuteScalar
Executes the query, and returns the first column of the first row in the result set returned by the query
ExecuteNonQuery
Executes a Transact-SQL statement against the connection and returns the number of rows affected
Your query doesn't return anything, so ExecuteScalar is not the right method to work with.
ExecuteNonQuery on the other side will give the correct information if your query has updated anything.

If you modify your SQL statement to the following, I think this will give you the result your expecting:
string sql = "
UPDATE StackOverflow SET UserName = #UserName
WHERE Id = #Id
RETURN #Id
";

Related

C# MySQL Order By Returns -1

I'm trying to get the last row of a table using C# but it doesn't seem to be working, this is my code:
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT ContactID FROM Contacten ORDER BY ContactID DESC LIMIT 1";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteNonQuery().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();
The value this returns is -1 while it should be returning 59.
The strange thing is is that when I run this command in phpmyadmin I DO get 59.
Any ideas on why C# is not returning the correct value but phpmyadmin is?
EDIT: problem solved, should've uses ExecuteScalar(). Looks like I've been staring at my monitor for a bit too long...
You need to use ExecuteScalar instead of ExecuteNonQuery.
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT ContactID FROM Contacten ORDER BY ContactID DESC LIMIT 1";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteScalar().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();
This should resolve your issue.
The value this returns is -1 while it should be returning 59.
No, it's behaving exactly as documented by IDbCommand.ExecuteNonQuery:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. For all other types of statements, the return value is -1.
You're using a SELECT statement - a query. So instead of executing ExecuteNonQuery, you should be using ExecuteQuery and iterating over the results, or ExecuteScalar, given that you know you'll have a single result:
string contactID = cmdGetID.ExecuteScalar().ToString();
you should use ExecuteScalar because you are returning value ExecuteNonQuery returns the number of rows affected by update delete or insert opeation
you can check this for more info
ExecuteNonQuery
Returns the number of rows affected.
ExecuteScalar
Executes the query, and returns the first column of the first row in
the result set returned by the query. Additional columns or rows are
ignored.
for more information you can check this The MySqlCommand Object
you can use query like this
MySqlConnection cnnGetID = new MySqlConnection(Global.connectionString);
cmd = "SELECT TOP 1 ContactID FROM Contacten ORDER BY ContactID";
MySqlCommand cmdGetID = new MySqlCommand(cmd, cnnGetID);
cnnGetID.Open();
string contactID = cmdGetID.ExecuteNonQuery().ToString();
MessageBox.Show(contactID);
cnnGetID.Close();

Execution status on INSERT and UPDATE - MS SQL Server

I am having a somewhat frustrating issue.
On the lower level: I want to be able to know whether an INSERT or UPDATE query in a proc was successful or not. I am not 100% sure if there is a status that is returned on all queries (apart from the SELECT). I know SQL Server gives a return type to all stored procs, and currently all mine have a return type of Integer.
On the middle level: In my repository, I want to use Entity Framework to call my stored procs and return the status as a converted (from int) boolean from the proc execution to my service.
On the higher level: I want to be able to use the returned boolean from my service to report back to an MVC controller on the task that was being performed.
On the most important layer of my issue, I have the following code:
public virtual ObjectResult<int> Proc_AddApprovalProcessor(string userId, string approverId, int approvalOrder)
{
return ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<int>(
"EXECUTE [dbo].[Proc_AddApprovalProcessor] #userId, #approverId, #approvalOrder",
new SqlParameter { ParameterName = "userId", Value = userId },
new SqlParameter { ParameterName = "approverId", Value = approverId },
new SqlParameter { ParameterName = "approvalOrder", Value = approvalOrder }).FirstOrDefault();
}
Make sure your insert/update stored procedures end with the following line:
SELECT ##ROWCOUNT
Then examine the return code and check that it is 1 (or however many rows you were expecting to insert/update).
You can use ##ROWCOUNT server variable immediately after the insert/update query to check number of affected rows by using the insert/update operation.
declare #fName varchar(50) = 'my name',
#lName varchar(50) = 'your name'
INSERT INTO myTable(fName,lName) values(#fName,#lName)
SELECT ##ROWCOUNT --> 0 - means no rows affected/nothing inserted or updated
--> 1 - means row has been inserted or updated successfully
if you are using transaction then have to use the below code to return the transaction count.
return ##TRANCOUNT;

Get Identify specification of Insert Query ado.net

I am inserting records in table with inline query.I have to get Identity generated by Insert statement by using Output Parameter, this is how I am doing
//Com.CommandText contains Insert Statment
OleDbParameter IDParameter = new OleDbParameter("#ID", OleDbType.Integer);
IDParameter.Direction = ParameterDirection.Output;
Com.Parameters.Add(IDParameter);
Com.ExecuteNonQuery();
After executing when I am checking the output parameter value,its appearing 0, althought record is inserting properly
this is how I am checking
Com.Parameters[0].Value
I also tried this
Com.Parameters["#ID"].Value
But output parameter value is always 0
I also tried using Select Scope_Identity() inside Insert statment but no luck,
I have also triend ExecuteScalar() but still same issue
Your insert query must end with
SELECT CAST(scope_identity() AS int)
Then ExecuteScaler() will return the identity.
int ID = (int)cmd.ExecuteScalar();

Return last inserted ID without using a second query

I'm working on an ASP.NET project (C#) with SQL Server 2008.
When I insert a row into a table in the database, I would like to get the last inserted ID, which is the table's IDENTITY (Auto Incremented).
I do not wish to use another query, and do something like...
SELECT MAX(ID) FROM USERS;
Because - even though it's only one query - it feels lame...
When I insert something I usually use ExecuteNonQuery(), which returns the number of affected rows.
int y = Command.ExecuteNonQuery();
Isn't there a way to return the last inserted ID without using another query?
Most folks do this in the following way:
INSERT dbo.Users(Username)
VALUES('my new name');
SELECT NewID = SCOPE_IDENTITY();
(Or instead of a query, assigning that to a variable.)
So it's not really two queries against the table...
However there is also the following way:
INSERT dbo.Users(Username)
OUTPUT inserted.ID
VALUES('my new name');
You won't really be able to retrieve this with ExecuteNonQuery, though.
You can return the id as an output parameter from the stored procedure, e.g. #userId int output
Then, after the insert, SET #userId = scope_identity()
even though it's only one query - it feels lame...
It actually is also wrong as you can have multiple overlapping iserts.
That is one thing that I always fuind funny - people not reading the documentation.
SELECT SCOPE_IDENTITY()
returns the last identity value generated in a specific scope and is syntactically correct. It also is properly documented.
Isn't there a way to return the last inserted ID without using another query?
Yes. Ask for the number in the saame SQL batch.
INSERT (blablab9a); SELECT SCOPE_IDENTITY ();
as ONE string. ExecuteScalar.
You can have more than one SQL statement in one batch.
If you want to execute query from C# code & want to get last inserted id then you have to find the following code.
SqlConnection connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
connection.Open();
string sql = "Insert into [Order] (customer_id) values (" + Session["Customer_id"] + "); SELECT SCOPE_IDENTITY()";
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
var order_id = cmd.ExecuteScalar();
connection.Close();
Console.Write(order_id);

Retrieve serial ID with Npgsql when inserting with ExecuteScalar

I'm trying to insert a row into a PostgreSQL table with a serial primary key and I need to retrieve this column after it was inserted. I got something like this:
The table "pais" has 3 columns: id, pais, capital; id is a serial column and is its primary key.
NpgsqlCommand query = new NpgsqlCommand("insert into pais(nombre, capital) values(#nombre, #capital)", conn);
query.Parameters.Add(new NpgsqlParameter("nombre", NpgsqlDbType.Varchar));
query.Parameters.Add(new NpgsqlParameter("capital", NpgsqlDbType.Varchar));
query.Prepare();
query.Parameters[0].Value = this.textBox1.Text;
query.Parameters[1].Value = this.textBox2.Text;
Object res = query.ExecuteScalar();
Console.WriteLine(res);
It inserts the row on the table but "res" value is null. If I insert with the nexval('table_sequence') also returns null.
Any idea of how can I return the id of the table? Am I missing something?
Thanks in advance
Is that thread safe?
What if another insert happens between your insert and select?
Why not use:
INSERT INTO table (fieldnames) VALUES (values) RETURNING idcolumn?
insert into pais(nombre, capital) values(#nombre, #capital) RETURNING id
replace id with your primary keyenter code here and use
Object res = query.ExecuteScalar();
Inside res you'll have the PK.
In order to select the last identity inserted you need to use: currval(sequencename)
so your select statement should look like:
NpgsqlCommand query = new NpgsqlCommand("insert into pais(nombre, capital) values(#nombre, #capital);select currval('table_sequence');", conn);
The insert itself does not cause a value to be returned. When you perform ExecuteScalar it is looking for a single value to be "Selected" so to speak.
I believe you need to follow up your insert with a select statement to solve your issue.
If you were using t-sql you would do this like so
string sql =
"INSERT INTO [Table] (FieldName) VALUES (#ParamName); "
+ "SELECT CAST(scope_identity() AS int)";
ExecuteScalar would then return the unique id;
I am not sure of the exact syntax for postGresql but hopefully this allows you to solve your issue.

Categories

Resources