SQL Server and C#: get last inserted id - c#

public static void CreateSocialGroup(string FBUID)
{
string query = "INSERT INTO SocialGroup (created_by_fbuid) VALUES (#FBUID); SELECT ##IDENTITY AS LastID";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#FBUID", FBUID);
connection.Open();
command.ExecuteNonQuery();
}
}
Is this the right way to do it? And how do i get LastID in to a variable? Thanks

OUTPUT clause?
string query = "INSERT INTO SocialGroup (created_by_fbuid)
OUTPUT INSERTED.IDCol --use real column here
VALUES (#FBUID)";
...
int lastId = (int)command.ExecuteScalar();

You can use ExecuteScalar to get the last value from a Sqlcommand.
The scope_identity() function is safer than ##identity.

If your server supports the OUTPUT clause you could try it with this one:
public static void CreateSocialGroup(string FBUID)
{
string query = "INSERT INTO SocialGroup (created_by_fbuid) OUTPUT INSERTED.IDENTITYCOL VALUES (#FBUID)";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("#FBUID", FBUID);
connection.Open();
var _id = command.ExecuteScalar();
}
}

Personally, I would re-write your code to use Parameters. You could either use an InputOutput parameter or an Output Parameter. However, using a Return Value in your SQL would also work.
Full examples on this can be found on MSDN.
I would also use Scope_Identity() rather than ##Identity this will ensure that you will reveice the ID that relates to the current transaction. Details on Scope_Identity can be found here.

U can try ExecuteScalar for getting the LastID value.

I'd recommend to use a stored procedure to do this. You can give it an OUTPUT parameter which you can use to return the id value back to your app.

cmd = new SqlCommand("Insert into table values (1,2,3); SELECT SCOPE_IDENTITY()", conn);
lastRecord = cmd.ExecuteScalar().ToString();

Use Stored Procedure only for the queries and use SCOPE_IDENTITY to get max value.

SqlCommand command = new SqlCommand("select max(id) from SocialGroup ", connection);
int lastId = (int)command.ExecuteScalar();

Related

Is this query to retrieve data from database correct?

I need to retrieve a value from a field in database. I have the used following code. but the value checkOrderId (which I need) shows the SQL string instead of the value from database. I don't know why it is doing so. Could somebody help me please?
string connectionString = "Data Source = xxyyzz;Initial Catalog = xyz; Integrated Security = True";
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From" + tableName + "ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
//cmd.ExecuteNonQuery();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == checkOrderId)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
I am new and dont have reputation to answer my question immediately. With everybody's help, i got this one solved...Great help, thanx everybody...following is my code.
string connectionString = "Data Source = EAEDEV;Initial Catalog = GIS; Integrated Security = True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string tableName = "[GIS].[SecondaryTraffic].[PotentialBackHauls]";
string checkOrderId = "Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
string valueReturned = (string)cmd.ExecuteScalar();
OpenPop.Pop3.Pop3Client popConn = new OpenPop.Pop3.Pop3Client();
if (orderIdentity == valueReturned)
{
popConn.DeleteMessage(messageNumber);
}
connection.Close();
}
You need to execute the query and check the results, here you are just comparing a string with the query SQL.
Please see here
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson03
for a tutorial.
Your expectation of the result being set into checkOrderId is incorrect. In this instance checkOrderId is just the query to execute and not the actual result.
You need to read the value back from executing the command:
using (var connection = new SqlConnection(connectionString))
using (var comm = new SqlCommand("Select TOP 1 OrderID From [GIS].[SecondaryTraffic].[PotentialBackHauls] ORDER BY InsertDate DESC", connection))
{
connection.Open();
object result = comm.ExecuteScalar(); // This is the key bit you were missing.
if (result != null)
{
// You can cast result to something useful
int orderId = (int)result;
}
} // Both comm and connection will have Dispose called on them here, no need to Close manually.
ExecuteScalar returns the value in the first cell (ie, column 1 row 1) as an object that you can cast to a better type (depending on what type it was in the result-set schema).
If you need to read multiple values, you need to look at ExecuteReader.
There are also other ways of doing this using output parameters, but that would pollute the point of the answer.
You can add space to your query
"Select TOP 1 OrderID From " + tableName + " ORDER BY InsertDate DESC";
Nota : I suggest you to use AddWithValue method with your parameter
string checkOrderId = "Select TOP 1 OrderID From #tableName ORDER BY InsertDate DESC";
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
cmd.Parameters.AddWithValue("#tableName", tableName );
Link : http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlparametercollection.addwithvalue.aspx
You don't actually run your command anywhere. Instead of the commented-out cmd.ExecuteNonQuery, you should look into the ExecuteScalar method, which allows you to read back a single result value from a query - which is what your query returns.
Add
int i = (Int32) cmd.ExecuteScalar();
right after
SqlCommand cmd = new SqlCommand(checkOrderId, connection);
then the variable i will contain the order id
No, this is not correct. You are comparing the variable orderId to your query string. I doubt that's what you want to do. I imagine you'd be better off calling cmd.ExecuteScalar() to retrieve the actual OrderID value. As noted by other answers, your query string is missing a space. But most importantly, it is bad practice to construct SQL queries in code. Although I can't see a security issue with this code, if you continue to use this method you will probably write code that is vulnerable to SQL injection. I recommend you learn to either use parameters or LINQ to build your queries.

to find max value from a given table in sql express

i am trying to retrieve latest data from my database table.
i am using max(columnName) but not having result to my liking.
i keep getting column name instead of any value
please help me out in this...
the code for retrieving max value is like this
dbConnection dbCon = new dbConnection();
con = dbCon.doConnection();
SqlCommand cmd = new SqlCommand();
String query = "select max(studentNo) from studentInfo;";
cmd.Connection = con;
cmd.CommandText = query;
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
String x=reader["studentNo"].ToString();
}
here the studentNo is the column name whose value i need to extract and it is of int type
while printing the string x on my application i get studentNo instead of the value.
now i am short of clue to solve the prob because i can't find anything wrong with the code.
do help me in this one
The problem is in the way you are accessing the value, you can change two things here. Either access the reader by index or name the column appropriately in the query.
select max(studentNo) as StudentNo from studentInfo;
Your query outputs one row and one column of data, so you might consider using ExecuteScalar() instead of ExecuteReader():
dbConnection dbCon = new dbConnection();
con = dbCon.doConnection();
SqlCommand cmd = new SqlCommand();
String query = "select max(studentNo) from studentInfo;";
cmd.Connection = con;
cmd.CommandText = query;
String x = cmd.ExecuteScalar().ToString();
You need to give alias to your select after applying aggregate function
i.e. select max(studentNo) as NO from studentInfo
and while reading it
String x=reader["NO"].ToString();
First you need to set the correct alias do the column:
select max(studentNo) as 'studentNo' from studentInfo;
And second, you may want to assign a database to the table:
select max(studentNo) as studentNo from databaseName..studentInfo;

Run stored procedure in C#, pass parameters and capture the output result

This is a simple task that I want to acheive but ASP.NET makes it quite difficult, next to impossible. I followed this question
Running a Stored Procedure in C# Button but found out ExecuteNonQuery does not return the output from query.
I tried this other approach but can't seem to pass the paremeters in this way
SqlConnection myConnection = new SqlConnection(myconnectionString);
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.SelectParameter <-- does not exist
Can someone write this simple code, how can I implement it? Basically I am passing a #username and #month (both character strings) to stored procedure and it returns a number that I want to capture and assign to a label control.
Thank you
The output from my query is this. It runs a complex query, create a temp table and then it runs
select ##rowcount
and I am capturing that.
Don't use SqlCommand.ExecuteNonQuery() if you actually want data from a result set.
Make sure your procedure uses set nocount on
Then use SqlCommand.ExecuteScalar()
return (int)myCommand.ExecuteScalar(); // value of select ##rowcount
Edit: As for your parameters:
myCommand.Parameters.AddWithValue("#username","jsmith");
myCommand.Parameters.AddWithValue("#month","January");
I prefer using linq-to-sql to handle stored procedures. Create a linq-to-sql model, where you add the SP you want to call. This will expose the SP as a function on the generated data context, where the parameters are ordinary C# functions. The returned values will be exposed as a collection of C# objects.
If you have multiple results from the SP things get a bit more complicated, but still quite straight forward.
Use the Parameters collection of the command to set the parameters, and the ExecuteScalar to run the query and get the value from the single-row single-column result.
Use using blocks to make sure that the connection and command are closed and disposed properly in any situation. Note that you have to provide the connection to the command object:
int result;
using (SqlConnection connection = new SqlConnection(myconnectionString)) {
using (SqlCommand command = new SqlCommand(connection)) {
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "usp_GetCustomer";
command.Parameters.Add("#username", SqlDbType.VarChar).Value = username;
command.Parameters.Add("#month", SqlDbType.VarChar).Value = month;
connection.Open();
result = (int)myCommand.ExecuteScalar();
}
}
using(SqlConnection myConnection = new SqlConnection(myconnectionString))
{
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.Parameters.Add("#USER_NAME", SqlDbType.VarChar).Value = sUserName; // user name that you pass to stored procedure
myCommand.Parameters.Add("#Month", SqlDbType.VarChar).Value = iMonth; // Month that you pass to stored procedure
// to get return value from stored procedure
myCommand.Parameters.Add("#ReturnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
myConnection .Open();
myCommand.ExecuteScalar();
// Returnvalue from stored procedure
return Convert.ToInt32(command.Parameters["#ReturnValue"].Value);
}
Simple code to get return value from SQL Server
SqlConnection myConnection = new SqlConnection(myconnectionString);
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "usp_GetCustomer";
myCommand.Parameters.Add("#USER_NAME", SqlDbType.VarChar).Value = sUserName; // user name that you pass to the stored procedure
myCommand.Parameters.Add("#Month", SqlDbType.VarChar).Value = iMonth; //Month that you pass to the stored procedure
// to get return value from the stored procedure
myCommand.Parameters.Add("#ReturnValue", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
myConnection .Open();
myCommand.ExecuteScalar();
// Returnvalue from the stored procedure
int iReturnValue = Convert.ToInt32(command.Parameters["#ReturnValue"].Value);

Specific cast is not valid, while retrieving scope_identity

I am getting exception: "Specific cast is not valid", here is the code
con.Open();
string insertQuery = #"Insert into Tender (Name, Name1, Name2) values ('Val1','Val2','Val3');Select Scope_Identity();";
SqlCommand cmd = new SqlCommand(insertQuery, con);
cmd.ExecuteNonQuery();
tenderId = (int)cmd.ExecuteScalar();
In the interests of completeness, there are three issues with your code sample.
1) You are executing your query twice by calling ExecuteNonQuery and ExecuteScalar. As a result, you will be inserting two records into your table each time this function runs. Your SQL, while being two distinct statements, will run together and therefore you only need the call to ExecuteScalar.
2) Scope_Identity() returns a decimal. You can either use Convert.ToInt32 on the result of your query, or you can cast the return value to decimal and then to int.
3) Be sure to wrap your connection and command objects in using statements so they are properly disposed.
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand(sql, connection))
{
connection.Open();
int tenderId = (int)(decimal)command.ExecuteScalar();
}
}
Try this:-
con.Open();
string insertQuery = #"Insert into Tender (Name, Name1, Name2) values ('Val1','Val2','Val3');Select Scope_Identity();";
SqlCommand cmd = new SqlCommand(insertQuery, con);
tenderId = Convert.ToInt32(cmd.ExecuteScalar());
EDIT
It should be this as it is correctly pointed out that scope_identity() returns a numeric(38,0) :-
tenderId = Convert.ToInt32(cmd.ExecuteScalar());
Note: You still need to remove the:-
cmd.ExecuteNonQuery();
Test the following first:
object id = cmd.ExcuteScalar()
Set a break point and have a look at the type of id. It is probably a Decimal and cannot directly be casted to int.
it needs Convert.ToInt32(cmd.ExecuteScalar());

Store value in a variable after using select statement

How to store the value of the PolicyID returned from database in an integer variable in C#?
I am using SQL server 2005.
System.Data.SqlClient.SqlConnection dataConnection = new SqlConnection();
dataConnection.ConnectionString =
#"Data Source=JAGMIT-PC\SQLEXPRESS;Initial Catalog=SumooHAgentDB;Integrated Security=True";
System.Data.SqlClient.SqlCommand dataCommand = new SqlCommand();
dataCommand.Connection = dataConnection;
dataCommand.CommandText = ("select PolicyID from Policies where PolicyID=(select max(PolicyID) from Policies)");
dataConnection.Open();
dataCommand.ExecuteNonQuery();
dataConnection.Close();
Please suggest.
Thanks.
Use the SqlCommand.ExecuteScalar method, like this:
command.CommandText = #"select max(PolicyID) from Policies";
int maxPolicyId = (int)command.ExecuteScalar();
Also, if you're doing this to insert a new Policy row with a unique ID, you must not do it like this, because it's entirely possible that a different Policies row will be inserted between the select and the insert.
Instead, use an IDENTITY column or a UNIQUEIDENTIFIER column.
EDIT: To use this in your code, do this:
int maxId;
using (SqlConnection dataConnection = new SqlConnection(#"Data Source=JAGMIT-PC\SQLEXPRESS;Initial Catalog=SumooHAgentDB;Integrated Security=True"))
using (SqlCommand dataCommand =
new SqlCommand("select max(PolicyID) from Policies", dataConnection)) {
dataConnection.Open();
maxId = Convert.ToInt32(dataCommand.ExecuteScalar());
}
DECLARE #id INTEGER
SELECT #id=PolicyID FROM ...
Did you just insert a new record into that policy table and now you want the ID given?
Then instead of a max(), use
SELECT SCOPY_IDENTITY()
to get the value that was assigned to your record, not to a record that happened to be inserted moments later.
You can also use SELECT IDENT_CURRENT('Policies') to get the value that was created for your record. To learn more about the differences between SCOPE_IDENTITY() AND IDENT_CURRENT('tablename'), check out this link.

Categories

Resources