How to store scope_identity value to a variable using datareader - c#

objcon.GetReader(" insert into product(name,price)Values('" + txt_name.Text + "','" + txt_price.Text + "') select scope_identity() ");
if (objcon.dr.Read())
{
var id = objcon.dr[0].ToString();
}
objcon.dr.Close();
I want to store the scope_identity value into a variable. The above code is working. But I am not getting the value in variable id. Can someone please help?

It has been a while since I last worked directly with ADO.Net, so this might not be 100% accurate.
var cmd = new SqlCommand(#"
insert into product(name,price) Values(#name, #price);
select scope_identity();", objCon);
cmd.Parameters.AddWithValue("#name", txt_name.Text);
cmd.Parameters.AddWithValue("#price", Convert.ToInt32(txt_price.Text));
var newId = (int)cmd.ExecuteScalar();
The SqlCommand object is ideal for performing queries that returns nothing, or a single value
ExecuteNonQuery() returns the number of affected rows. F.ex. how many row was actually updated, inserted, or deleted (note: triggers can affect this value)
ExecuteScalar() returns the first column of the first row, in the result, and ignores the rest. It's perfect to retrieving a newly inserted ID or a count, or a sum, etc. The returned type is object, but can be cast to the expected type.

Related

Getting Total number of records in c#

I am trying to get total number of records when the following query is run:
var cmd =new SqlCommand("SELECT * FROM Issue where BookID = #bid and IssueDate = #idate order by IssueDate desc", conn);
cmd.Parameters.AddWithValue("bid", bookid);
cmd.Parameters.AddWithValue("idate", DateTime.Now);
int val = cmd.ExecuteNonQuery();
There is a record available in the database, but val always return -1.
Problem : You are trying to execute the query which returns the actual records from the table but not the Records count.
Solution : To get the Total Records from the Table, you need to call the Query as below:
Syntax:
SELECT COUNT(*) FROM [TABLENAME];
Note : To Read the records count you can either call ExecuteReader() or ExecuteScalar() methods.
but i would strongly recommned to call ExceuteScalar() when there is only one record/value to read.
EDIT: You don't need order by clause here as order of records will not effect the count value.
Try This:
var cmd =new SqlCommand("SELECT COUNT(*) FROM Issue where BookID = #bid and
IssueDate = #idate");
cmd.Parameters.AddWithValue("bid", bookid);
cmd.Parameters.AddWithValue("idate", DateTime.Now);
int totalRecords = Convert.ToInt32(cmd.ExecuteScalar());
You can either iterate through all records or make another query to count them yourself.
Also, don't forget to wrap your SqlCommand to a using statement because it implements the IDisposable interface.
From 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.
So you should use the already proposed COUNT based solutions.

Query is always returning -1 in C#

I am using following code to check if record exist.
SqlCommand check_Campaign_Name = new SqlCommand("SELECT * FROM Campaign_Summary WHERE ([Compaign_Name] = #user) ", conn);
check_Campaign_Name.Parameters.AddWithValue("#user", txtBox_LastClick_Campaign.Text);
int CampaignExist = check_Campaign_Name.ExecuteNonQuery();
richTextBox1.Text = CampaignExist.ToString();
But I am always getting -1 in the integer CampaignExist. Don't know where I am doing wrong.
ExecuteNonQuery is not supposed to return the number of rows SELECTED, but the number of rows modified by an INSERT/UPDATE/DELETE command. You should use a SqlDataReader and check with its property HasRows or use an aggregate function like COUNT and ExecuteScalar
(Probably the best choiche if you want to just retrieve the number of rows)
SqlCommand check_Campaign_Name = new SqlCommand("SELECT COUNT(*) FROM Campaign_Summary " +
"WHERE Compaign_Name = #user", conn);
check_Campaign_Name.Parameters.AddWithValue("#user", txtBox_LastClick_Campaign.Text);
int rowCount = Convert.ToInt32(check_Campaign_Name.ExecuteScalar());
However, if you want only to know if the row exists or not, then the COUNT approach is considered less efficient than using the EXISTS statement.
string cmdText = #"IF EXISTS (SELECT Compaign_Name FROM Campaign_Summary
WHERE Compaign_Name = #user)
SELECT 1 ELSE SELECT O";
SqlCommand check_Campaign_Name = new SqlCommand(cmdText, conn);
int rowExists = Convert.ToInt32(check_Campaign_Name.ExecuteScalar());
This second approach just allows to know if there are rows that fits the WHERE statement or not.
So it is not exactly like COUNT(*) where you get the exact number of rows.
Use executescalar method and count on query
SqlCommand check_Campaign_Name = new SqlCommand("SELECT COUNT(1) FROM Campaign_Summary WHERE ([Compaign_Name] = #user) ", conn);
check_Campaign_Name.Parameters.AddWithValue("#user", txtBox_LastClick_Campaign.Text);
int CampaignExist = Convert.ToInt32(check_Campaign_Name.ExecuteScalar());
richTextBox1.Text = CampaignExist.ToString();
From 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.
As your query is a SELECT and not one of the mentioned UPDATE, INSERT or DELETEs, it will always return -1.
Try with Execute scalar MSDN
int CampaignExist = Convert.ToInt(check_Campaign_Name.ExecuteScalar());
SqlCommand check_Campaign_Name = new SqlCommand("SELECT COUNT(1) FROM Campaign_Summary WHERE ([Compaign_Name] = #user) ", conn);
check_Campaign_Name.Parameters.AddWithValue("#user", txtBox_LastClick_Campaign.Text);
int CampaignExist = Convert.ToInt32(check_Campaign_Name.ExecuteScalar());
richTextBox1.Text = CampaignExist.ToString();
ExecuteNonQuery is not used to retrieve results
You can use one of the following methods:
SqlCommand.ExecuteScalar (I would prefer this)
DataAdapter.Fill

Executing an insert statement and put id in a local variable?

SqlDataSource myQuiz = new SqlDataSource();
myQuiz.ConnectionString = ConfigurationManager.ConnectionStrings["yafnet"].ToString();
myQuiz.InsertCommand = "INSERT INTO [QuizTable]([Quiz_Title],[Quiz_Description]) VALUES (#Quiz_Title,#Quiz_Description)";
myQuiz.InsertParameters.Add("Quiz_Title",Quiz_Title.Text);
myQuiz.InsertParameters.Add("Quiz_Description",Quiz_Description.Text);
myQuiz.Insert();
Response.Redirect("QuizQuests.aspx");
Is there a way to get back the automatically generated ID of the new row and put it in a local variable?
Thanks a lot in advance,
Adrian
Use
SELECT IDENT_CURRENT(‘QuizTable’)
It returns the last IDENTITY value produced in a table, regardless of the connection that created the value, and regardless of the scope of the statement that produced the value.
IDENT_CURRENT is not limited by scope and session; it is limited to a specified table. IDENT_CURRENT returns the identity value generated for a specific table in any session and any scope.
If you want to be 100% sure that you really get the identity from your insert in your actual QuizTable, you should use SCOPE_IDENTITY() (as already mentioned by Luiggi Mendoza in his comment), and not ##IDENTITY or IDENT_CURRENT.
##IDENTITY might not work because it will return the identity from the last insert that happened from your connection. So if there is a trigger on your QuizTable which inserts a row in another table that has an identity column as well, ##IDENTITY will return the value from that second insert, and not that of the original insert into the QuizTable .
IDENT_CURRENT will return the last identity value for your table (and only for your table, so it doesn't matter if there are triggers like the one in the previous example).
But it returns the last identity value for any session. So if another row is inserted from another session between your INSERT and your IDENT_CURRENT, you'll get the identity value from that row, not from yours.
#Adrian De Barro: hi you can use following code to get inserted record id and save in variable
in your sqlquery add following statement:
return ##IDENTITY
and your C# code will be as follows:
SqlConnection cn = new
SqlConnection(ConfigurationManager.AppSettings["ConnectionString"]);
cn.Open();
SqlCommand cmd = new SqlCommand(procname, cn);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter str = new SqlParameter("name", SqlDbType.VarChar);
str.Direction = ParameterDirection.ReturnValue;
foreach (SqlParameter par in param)
{
cmd.Parameters.Add(par);
}
string name = Convert.ToString(cmd.ExecuteScalar());
cmd.Dispose();
cn.Close();
return name;

Proper SQL query command with SQL Compact is failing

I've got a function that stores temporary information generated for every user authenticated in the system. This 'session ID' is a string stored in a Sessions table, along the original ID of the user which authenticated and was given said session identifier.
The function to remove/deauthenticate/invalidate an existing session first checks if the user exists through another method implemented as follows:
int userId = 0;
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#User", userName);
cmd.Connection = this.conn;
cmd.CommandText = "SELECT Id FROM Users WHERE (Username = #User)";
userId = (int) cmd.ExecuteScalar()
cmd.Dispose();
Afterwards it tries to find an existing session for that user, which is to be removed (via a different method again):
SqlCeCommand cmd = new SqlCeCommand();
SqlCeParameterCollection sqlParams = cmd.Parameters;
sqlParams.AddWithValue("#SID", mysession);
sqlParams.AddWithValue("#UID", myuserid);
cmd.Connection = this.Connection;
cmd.CommandText = "SELECT Id FROM UserSessions WHERE (SessionID = #SID) AND (User_Id = #UID)";
int foo = cmd.ExecuteNonQuery();
...which fails. No exception is raised unfortunately. So I added an insecure equivalent using a non parametrized query string:
cmd.CommandText = String.Format("SELECT Id FROM UserSessions WHERE (SessionID = '{0}') AND (User_Id = {1})", mysession, myuserid);
cmd.Prepare();
int bar = cmd.ExecuteNonQuery();
Added a breakpoint, paused, copy pasted the query into the Visual Studio Query tool and voila, it indeed worked. But after continuing, that query in the code failed as well. I'm unable to find the culprit of this annoying issue since no exception is raised and everything seems correct. The data exists, the parameters are provided in proper types (string and int) and I'm out of things to check. The connection is open and so forth.
Any clues from anyone around? Thanks!
Update: Mea culpa, missed the fact that the function used ExecuteScalar until I modified it for testing. It does use ExecuteScalar and returns null, just in case.
You're using ExecuteNonQuery:
int foo = cmd.ExecuteNonQuery();
... but you're clearly trying to execute a query (a SELECT)! Use ExecuteScalar again, as you did in the first code, or ExecuteReader and look through the results appropriately. If you stick with ExecuteScalar, you should first check whether the result is null to indicate no results.
ExecuteNonQuery returns the number of rows affected by an UPDATE/INSERT/DELETE command - which is what it's intended for. I suspect it's returning -1 for you, as documented:
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.
(Emphasis mine.)
Use set [] to avoid ambiguity with database keyword.
cmd.CommandText = "SELECT [Id] FROM [Users] WHERE ([Username] = #User)";
and use ExecuteScalar() or ExecureReader() method when working with SELECT statements.

c# ExecuteNonQuery always returns Zero

I think nothing's wrong with the connection because when I open it, it does not throw any error. So I guess the error is when I'm executing a command. This is my code:
OleDbCommand cmd = new OleDbCommand("SELECT * FROM cars", conn);
cmd.CommandType = CommandType.Text;
int numbers = cmd.ExecuteNonQuery();
I tried using a message box to display the value of numbers but the result is always 0. The table cars contains 5 records. So why am I not getting the correct results?..
To the anonymous downvoter, the key part of the OP:
I tried using a message box to display the value of numbers but the
result is always 0. The table cars contains 5 records. So why am I not
getting the correct results?..
The OP is obviously trying to get a count of records in the table (a scalar aggregate) and not all of the table data.
My answer:
That's because your query is returning a table and not a scalar value and you're calling the incorrect function. Your query should be should be:
"SELECT COUNT(*) FROM cars"
And ExecuteNonQuery doesn't actually expect any results to be returned. (You usually run insert, update and delete operations with ExecuteNonQuery.) You should be using ExecuteScalar which expects a single-valued result such as count(*).
All together now:
OleDbCommand cmd = new OleDbCommand("SELECT count(*) FROM cars", conn);
cmd.CommandType = CommandType.Text;
int numbers = cmd.ExecuteScalar();
Try using ExecuteScalar that should give you the count. ExecuteNonQuery doesn't return the results from your query. The return your looking at indicates how many rows were affected by your statement, in your case zero.
ExecuteNonQuery as the name tells you does not make a query. it is normally used for inserts or updates and returns the number of affected records. for the query you provided you should use ExecuteReader or a DataAdapter and its Fill method to fill a datatable.
Because you are executing a query, and ExecuteNonQuery returns the number of rows effected, which when you select is always 0 since you aren't changing anything (ie. INSERT,UPDATE or DELETE)
ExecuteNonQuery only returns the number of rows affected for UPDATE, DELETE or INSERT operations. For the number of rows in the SELECT statement, try:
OleDbCommand cmd = new OleDbCommand("SELECT * FROM cars", conn);
OleDbDataReader reader = cmd.ExecuteReader();
int numbers = 0;
while (reader.Read())
{
//// other Reader-related operations here...
numbers++;
}

Categories