ExecuteNonQuery doesn't return value? - c#

I am trying to write a common Save function and I am using Dbcommand. My code is:
private static int Save(CommandType commandtype, string commandText, SqlParameter[] commandParameters, bool p)
{
int id = -1;
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandType = commandtype;
command.CommandText = commandText;
foreach(SqlParameter pa in commandParameters)
{
command.Parameters.Add(pa);
}
connection.Open();
id = command.ExecuteNonQuery();
}
}
return id;
}
Where am I going wrong? The code saves the value in the database.

Please delete the line in the SP SET NOCOUNT ON; in the SP so you will get
the value

ExecuteNonQuery returns the number of rows affected.
If your SQL statement is something like
insert into ... values ...
select ##identity
Then you need to use ExecuteScalar instead.

For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
look at msdn
But I don't understand what do you mean when you said that the method ExecuteNonQuery should return value.
If you want to return a value you should use the ExecuteScalar

Execute Scalar returns only 1 row..and executenonquety returns affected rows only...
ExecuteNonQuery doesnt give u return values...

Related

Check if update statement was successful

I have the following method that sets an object to a specific status (it sets a column value of a specific row to '4' :
C#
void setObjectToFour(int objectID)
{
using (var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Database"].ConnectionString))
using (var command = new SqlCommand("setObjectToFour", conn)
{
CommandType = CommandType.StoredProcedure
})
{
command.Parameters.Add(new SqlParameter("#objectID", SqlDbType.Int)).Value = objectID;
conn.Open();
command.ExecuteNonQuery();
}
}
SQL:
...
AS
BEGIN
Update [DB_OBJECT].[dbo].[object_table]
SET status = 4
WHERE id = #objectID
END
The problem is that the DB_OBJECT DB is not managed by us and is the DB of a piece of software.
The followed problem is that the query from above not always works (and we haven't figured out why) and I were thinking about how we could 'force' or 'check' if the row was updated.
Is it smart to do it as follow?:
1 - Create new C# Method Check and stored procedure getStatus that retrieves the status of the object
2 - I will put both methods from above in a do while until the status is 4.
Is this a smart approach?
ExecuteNonQuery() method returns the number of rows affected.
int recordAffectd = command.ExecuteNonQuery();
if (recordAffectd > 0)
{
// do something here
}
ExecuteNonQuery() does not return data at all: only the number of rows affected by an insert, update, or delete.
try this
if (command.ExecuteNonQuery() != 0)
{
// more code
}

Execute non query returns negetive one(-1) but still inserts [duplicate]

For some reason, ExecuteNonQuery() in C# returns -1, though when I run a query separately, the value returns the actual value needed.
For Example:
try
{
var connString ="Data Source=ServerName;InitialCatalog=DatabaseName;Integrated Security=true;"
SqlConnection conn = new SqlConnection(connString);
SqlCommand someCmd = new SqlCommand("SELECT COUNT(*) FROM SomeTable");
someCmd.Connection = conn;
conn.Open();
var theCount = cmd.ExecuteNonQuery();
conn.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
When the command is executed it returns -1. Though if run the query separately,
SELECT COUNT(*) FROM SomeTable;
Column returns one row with a count of 4 if that table being queried has 4 rows.
Based on MSDN:
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
You want to return the number of rows affected by the command and save it to an int variable but since the type of statement is select so it returns -1.
Solution: If you want to get the number of rows affected by the SELECT command and save it to an int variable you can use ExecuteScalar.
var theCount = (int)cmd.ExecuteScalar();
You can use Ef core with Ado.net like this example
var context = new SampleDbContext();
using (var connection = context.Database.GetDbConnection())
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT COUNT(*) FROM SomeTable";
var result = command.ExecuteScalar().ToString();
}
}

Select query to get data from SQL Server

I am trying to run the SQL Select query in my C# code. But I always get the -1 output on
int result = command.ExecuteNonQuery();
However, the same table if I use for delete or insert works...
ConnectString is also fine.
Please check below code
SqlConnection conn = new SqlConnection("Data Source=;Initial Catalog=;Persist Security Info=True;User ID=;Password=");
conn.Open();
SqlCommand command = new SqlCommand("Select id from [table1] where name=#zip", conn);
//command.Parameters.AddWithValue("#zip","india");
int result = command.ExecuteNonQuery();
// result gives the -1 output.. but on insert its 1
using (SqlDataReader reader = command.ExecuteReader())
{
// iterate your results here
Console.WriteLine(String.Format("{0}",reader["id"]));
}
conn.Close();
The query works fine on SQL Server, but I am not getting why only select query is not working.
All other queries are working.
SqlCommand.ExecuteNonQuery Method
You can use the ExecuteNonQuery to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database without using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or return values mapped to parameters are populated with data.
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
SqlCommand.ExecuteScalar Method
Executes a Transact-SQL statement against the connection and returns the number of rows affected.
So to get no. of statements returned by SELECT statement you have to use ExecuteScalar method.
Reference: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery(v=vs.110).aspx
So try below code:
SqlConnection conn = new SqlConnection("Data Source=;Initial Catalog=;Persist Security Info=True;User ID=;Password=");
conn.Open();
SqlCommand command = new SqlCommand("Select id from [table1] where name=#zip", conn);
command.Parameters.AddWithValue("#zip","india");
// int result = command.ExecuteNonQuery();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
Console.WriteLine(String.Format("{0}",reader["id"]));
}
}
conn.Close();
According to MSDN
http://msdn.microsoft.com/ru-ru/library/system.data.sqlclient.sqlcommand.executenonquery(v=vs.110).aspx
result is the number of lines affected, and since your query is select no lines are affected (i.e. inserted, deleted or updated) anyhow.
If you want to return a single row of the query, use ExecuteScalar() instead of ExecuteNonQuery():
int result = (int) (command.ExecuteScalar());
However, if you expect many rows to be returned, ExecuteReader() is the only option:
using (SqlDataReader reader = command.ExecuteReader()) {
while (reader.Read()) {
int result = reader.GetInt32(0);
...
}
}
you can use ExecuteScalar() in place of ExecuteNonQuery() to get a single result
use it like this
Int32 result= (Int32) command.ExecuteScalar();
Console.WriteLine(String.Format("{0}", result));
It will execute 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.
As you want only one row in return, remove this use of SqlDataReader from your code
using (SqlDataReader reader = command.ExecuteReader())
{
// iterate your results here
Console.WriteLine(String.Format("{0}",reader["id"]));
}
because it will again execute your command and effect your page performance.
That is by design.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery(v=vs.110).aspx
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
you have to add parameter also #zip
SqlConnection conn = new SqlConnection("Data Source=;Initial Catalog=;Persist Security Info=True;User ID=;Password=");
conn.Open();
SqlCommand command = new SqlCommand("Select id from [table1] where name=#zip", conn);
//
// Add new SqlParameter to the command.
//
command.Parameters.AddWithValue("#zip","india");
int result = (Int32) (command.ExecuteScalar());
using (SqlDataReader reader = command.ExecuteReader())
{
// iterate your results here
Console.WriteLine(String.Format("{0}",reader["id"]));
}
conn.Close();
You should use ExecuteScalar() (which returns the first row first column) instead of ExecuteNonQuery() (which returns the no. of rows affected).
You should refer differences between executescalar and executenonquery for more details.
Hope it helps!

ExecuteNonQuery() Returns unexpected number of rows affected C#

Here's my code
// SqlCommand query = new SqlCommand("INSERT INTO devis (idProposition, identreprise, tauxHoraire, fraisGenerauxMO, fraisGenerauxPiece, beneficeEtAleas, idStatut, prixUnitaireVenteMO ) VALUES(#idproposition, #identreprise, #tauxHoraire, #fraisGenerauxMO, #fraisGenerauxPiece, #beneficeEtAleas, 1, #prixUnitaireVenteMO) ", Tools.GetConnection());
SqlCommand query = new SqlCommand("INSERT INTO devis (idProposition, identreprise, tauxHoraire, fraisGenerauxMO, fraisGenerauxPiece, beneficeEtAleas, idStatut, prixUnitaireVenteMO, alerteEntrepriseEnvoyee,fraisDeplacement ) VALUES(1051, 85, 20, 2, 2, 2.2, 1, 88,0,-1) ", Tools.GetConnection());
//query.Parameters.AddWithValue("idproposition", this.ID);
//query.Parameters.AddWithValue("identreprise", competitor.ID);
//query.Parameters.AddWithValue("tauxHoraire", competitor.CoefTauxHoraire);
//query.Parameters.AddWithValue("fraisGenerauxMO", competitor.CoefFraisGenerauxMO);
//query.Parameters.AddWithValue("fraisGenerauxPiece", competitor.CoefFraisGenerauxPiece);
//query.Parameters.AddWithValue("beneficeEtAleas", competitor.CoefBeneficeEtAleas);
//query.Parameters.AddWithValue("prixUnitaireVenteMO", Math.Round(competitor.CoefTauxHoraire * competitor.CoefFraisGenerauxMO * competitor.CoefBeneficeEtAleas, 2));
bool insertOK = (query.ExecuteNonQuery() == 1);
if (insertOK)
{
// DO SOMETHING
}
insertOk is false but in the database the row is inserted with all the information that I specified
I rebuilt the query manually to see if the problem came from the query.Parameters, it inserts without error again into the database but insertOk is still false! I even added two other fields which aren't supposed to be null but the activity is the same in both cases
any ideas?
ExecuteNonQuery it claims to return The number of rows affected.. This is incorrect, as there is no way for the client to know the number of rows affected. The documentation incorrectly assumes that the engine will report the number of rows affected, but that is subject to the session SET NOCOUNT state. Do not write code that assumes the NOCOUNT is always on. If you need to know the number of rows affected use the OUTPUT clause. Relying on the ##ROWCOUNT or the SET NOCOUNT state is subject to many many corner cases where the value is incorrect from one point of view or another.
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command.
When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
ExecuteNonQuery method returns System.Int32
Executes a Transact-SQL statement against the connection and returns
the number of rows affected.
Return Value
Type: System.Int32
The number of rows affected.
Since your query.ExecuteNonQuery() returns 2, it is too obvious 2 == 1 returns false.
Your query will be;
bool insertOK = (2 == 1);
DEMO.
Try using SqlDataAdapter such that :
SqlDataAdapter Adabter = new SqlDataAdapter();
Adabter.InsertCommand = new SqlCommand("INSERT INTO devis values(#idProposition, #identreprise), Tools.GetConnection());
Adabter.InsertCommand.Parameters.Add("#idproposition",SqlDbType.Int).Value = yorID;
Adabter.InsertCommand.Parameters.Add("#identreprise", SqlDbType.Int).Value = yorID;
Tools.OpenConnection();
int result = Adabter.InsertCommand.ExecuteNonQuery();
Tools.CloseConnection();
if( result > 0 )
{
MessageBox.Show("Information Added");
}else
{
MessageBox.Show("Error");
}
Same issue here with an UPDATE query. In my case I had to add "set nocount off" to the SQL. Example code:
string sql =
$#"set nocount off;update PRODUCT_PLAN
set WORKING_STATUS = 'P',
user_id = #USER_ID
where workorder_base_id = #BASE_ID
";
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandType =CommandType.Text;
cmd.Parameters.AddWithValue("#USER_ID", opl.USER_ID);
cmd.Parameters.AddWithValue("#BASE_ID", opl.WORKORDER_BASE_ID);
cmd.CommandText = sql;
// Nr of rows updated in retval
int retval = cmd.ExecuteNonQuery();

SQL connection commands doesn't change the data

How can I know whether the table in database is affected after these instructions? I try to show the query result in console but it doesn't show anything.
static void Main(string[] args)
{
DateTime date = new DateTime(2013, 3, 4);
try
{
SqlConnection connection = new SqlConnection("Data Source=ExchangeRatesByDate/TestApplication/Rates_DB.sdf");
Console.WriteLine("Connection is created");
connection.Open();
Console.WriteLine("Connection is opened");
SqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)";
insertCommand.ExecuteNonQuery();
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Rates_Table", connection);
DataTable data = new DataTable();
adapter.Fill(data);
Console.WriteLine(adapter);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
ExecuteNonQuery() returns an integer showing number of affected rows. ExecuteNonQuery
You can use the ExecuteNonQuery to perform catalog operations (for
example, querying the structure of a database or creating database
objects such as tables), or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
try like this
int updatedRows = insertCommand.ExecuteNonQuery();
if(updatedRows>0)
{
//do something
}
i think u are showing SqlDataAdapter object show to datatable ,and also use parameter for the insert string like 'USD'
the ExecuteNonQuery() returns an integer for the number of affected records.
int _affected = insertCommand.ExecuteNonQuery();
ExecuteNonQuery()
follow-up question
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)
in the statement above, are values USD and date are real values because if so, it pretty sure it will thrown an exception. It should be wrap with single quotes like this:
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES ('USD', 1, 417.5, '')
because they are string literals. But it's not the proper way to insert data with real values in the INSERT statement. The values should be parameterized to avoid sql injection.
string sqlStatement = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (#iso, #Amount, #rate, #date)";
using (SqlConnection conn = new SqlConnection(connStr))
{
using(SqlCommand comm = new SqlCommand())
{
comm.Connection = conn;
comm.CommandText = sqlStatement;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#iso", '-- value --');
comm.Parameters.AddWithValue("#Amount", '-- value --');
comm.Parameters.AddWithValue("#rate", '-- value --');
comm.Parameters.AddWithValue("#date", '-- value --');
try
{
conn.Open();
int _affected = comm.ExecuteNonQuery();
}
catch(SqlException e)
{
// do something with the exception
// do not hide it
// e.Message.ToString()
}
}
}
For proper coding
use using statement for propr object disposal
use try-catch block to properly handle objects

Categories

Resources