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!
Related
I have a table in sqlite that contains many columns like id,number,name
id is primary and auto increment , when i try to get the last id inserted in The table "Data" it returns "-1"
The connection :
SQLiteConnection con = new SQLiteConnection(#"Datasource =|DataDirectory|\SmartScale.db");
The code i use :
con.Open();
SQLiteCommand cmd=new SQLiteCommand("SELECT MAX(id) FROM Data", con);
int id= cmd.ExecuteNonQuery();
tId.Text =Convert.ToString(id);
con.Close();
You don't want to use ExecuteNonQuery for that, ExecuteScalar is more appropriate because it gives you the first column of the first row in the result set.
When using ExecuteNonQuery, the -1 is what you always get for select statements. For inserts, updates or deletes the return value is the number of rows affected by the statement.
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();
}
}
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
I have this code and it always returns -1.I have three tables (a picture is more suggestive ):
I want to see if the row is already in the ReservationDetails table, and if it's not to insert it.
try
{
SqlConnection conn = new SqlConnection...
SqlCommand slct = new SqlCommand("SELECT * FROM ReservationDetails WHERE rID=#rID AND RNumber=#RNumber", conn);
slct.Parameters.AddWithValue("#rID", (int)comboBox1.SelectedValue);
slct.Parameters.AddWithValue("#RNumber", dataGridView1.SelectedRows[0].Cells[0].Value);
int noRows;//counts if we already have the entry in the table
conn.Open();
noRows = slct.ExecuteNonQuery();
conn.Close();
MessageBox.Show("The result of select="+noRows);
if (noRows ==0) //we can insert the new row
Have you read the documentation of SqlCommand.ExecuteNonQuery?
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.
And your query is SELECT.
You should
1) Change your TSQL to
SELECT COUNT(*) FROM ReservationDetails WHERE ...
(better still, use IF EXISTS ...)
2) and use ExecuteScalar():
noRows = (int) slct.ExecuteScalar();
Also: you will need to use a transaction (or some other atomic technique), or else someone could insert a row in-between you testing and trying to insert it...
All that said, it would be better to create a stored procedure that given your parameters, atomically tests and inserts into the table, returning 1 if successful, or 0 if the row already existed.
It is better to do it in a single query so that you do not need to request server two times.
Create a procedure like this and call it from the code.
IF EXISTS (SELECT 1 from ReservationDetails WHERE rID=#rID AND RNumber=#RNumber)
BEGIN
insert into ReservationDetails values(#rID,#RNumber)
END
As per Microsoft:
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.
What you may need, instead of ExecuteNonQuery is ExecuteScalar and put the COUNT in your select query.
i.e.
SqlCommand slct = new SqlCommand("SELECT COUNT(*) FROM ReservationDetails WHERE rID=#rID AND RNumber=#RNumber", conn);
Also, try to make use of the using statement in C#, so you don't need to worry about closing the connection manually, even if things fail.
i.e.
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
try
{
conn.Open();
newProdID = (Int32)cmd.ExecuteScalar();
}
catch (Exception ex)
{
//Do stuff
}
}
see:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar.aspx
#nickNatra
When ever you use
Select command
It will return you values. Which can be either used by
DataSet or SqlDataReader
But
command.ExecuteNonQuery()
is used only when you are using
Insert , Update , Delete where the Rows are getting effected in your table
Yes, If you do want to know how much records are there in your query.
You can perform
a) Modify your query "select count(*) from table"
where you will only get one value ie. Number of Rows.
b) Using this query perform command. ExecuteScalar() which will return only First row and first column which is the Row Count
Hence this satisfy's your requirement.
Cheers!!
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...