Get output parameter for ID (primary key) - c#

I have a simple database which has an ID column as primary key, INT, AUTO_INCREMENT and a name column.
I'm trying to insert values into the database and get the ID back. This is part of my code:
using (var connection = new MySqlConnection(...))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText =
"INSERT INTO `adressbook`.`Person` (`ID`, `Name`)
VALUES (#id, #name);";
var idParameter = new MySqlParameter("id", MySqlDbType.Int32);
idParameter.Direction = ParameterDirection.Output;
idParameter.SourceColumn = "ID";
command.Parameters.Add(idParameter);
command.Parameters.AddWithValue("name", "Test");
command.ExecuteNonQuery();
var id = command.Parameters["id"].Value;
connection.Close();
}
However, I always get NULL as the value, even if I can see that the value has been inserted into the database (so the connection settings etc. are fine).
What I have tried
I have read MySQL Connector/NET Output Parameter Returning NULL and Get the value from Output parameter C#, but it still doesn't work if I change my code to
var reader = command.ExecuteReader();
reader.Read();
reader.Close();
I have read the related post Executing MySqlCommand (StoredProcedure) with output parameter, but it didn't help me since I am already using the correct MySql data type.

Just use the LAST_INSERT_ID function of MySql.
using (var connection = new MySqlConnection(...))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = #"INSERT INTO `adressbook`.`Person` (`Name`) VALUES (#name);
SELECT LAST_INSERT_ID();";
command.Parameters.AddWithValue("#name", "Test");
int result = Convert.ToInt32(command.ExecuteScalar());
.......
}
As you can see, you can send multiple commands to MySql with a single execution.
The LAST_INSERT_ID function returns the last autoincrement value.
However, in this scenario, you need to call ExecuteScalar instead of ExecuteNonQuery because the command will return a single row with a single value.
By the way, if you have an Auto_increment column then don't pass anything for that column.

Related

insert value from TextBox into sql

I'm getting this error message: Cannot insert the value NULL into column 'id', table ''; column does not allow nulls. INSERT fails. thanks in advance
protected void AddItem(object sender, EventArgs e)
{
string insertCmd = "INSERT INTO Picture (Album, id) VALUES (#Album, #id)";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["strConn"].ConnectionString))
{
conn.Open();
SqlCommand myCommand = new SqlCommand(insertCmd, conn);
// Create parameters for the SqlCommand object
// initialize with input-form field values
myCommand.Parameters.AddWithValue("#Album", txtAlbum.Text);
myCommand.Parameters.Add("#id", SqlDbType.Int).Direction = ParameterDirection.Output;
myCommand.ExecuteNonQuery();
int id = (int)myCommand.Parameters["#id"].Value;
}
}
I suppose that ID is an IDENTITY column. Its value is generated automatically by the database engine and you want to know what value has been assigned to your record.
Then you should change your query to
string insertCmd = #"INSERT INTO Picture (Album) VALUES (#Album);
SELECT SCOPE_IDENTITY()";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["strConn"].ConnectionString))
{
conn.Open();
SqlCommand myCommand = new SqlCommand(insertCmd, conn);
myCommand.Parameters.AddWithValue("#Album", txtAlbum.Text);
int newID = Convert.ToInt32(myCommand.ExecuteScalar());
}
The query text now contains a second instruction SELECT SCOPE_IDENTITY() separated from the first command by a semicolon. SCOPE_IDENTITY returns the last IDENTITY value generated for you by the database engine in the current scope.
Now the command is run using the ExecuteScalar to get back the single value returned by the last statement present in the query text without using any output parameter
I would think that ID is identity. You don't have to add this value. I would try the following code and check the database if you get automatically an ID.
string insertCmd = "INSERT INTO Picture (Album) VALUES (#Album)";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["strConn"].ConnectionString))
{
conn.Open();
SqlCommand myCommand = new SqlCommand(insertCmd, conn);
// Create parameters for the SqlCommand object
// initialize with input-form field values
myCommand.Parameters.AddWithValue("#Album", txtAlbum.Text);
myCommand.ExecuteNonQuery();
}
I case you want to set the id yourself(withoud automatic increment from the db), you should change the schema of the database removing identity from ID as shown below:
I hope this helps
If you need to stay this column empty you can try to replace to ' '(blank). This will work if you column is not "Key"
Or try to use:
substitute a value when a null value is encountered
NVL( string1, replace_with )
You can do this using stored procedure. Below is the script for Create stored procedure.
CREATE PROCEDURE [dbo].[InsertIntoPicture]
#Album varchar(500)=null,
#id int=0 output
AS
BEGIN
insert INTO Picture(Album)VALUES(#Album)
SET #id=##IDENTITY
END
Below is the code for call stored procedure with C# .
string insertCmd = "InsertIntoPicture";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["strConn"].ConnectionString))
{
conn.Open();
SqlCommand myCommand = new SqlCommand(insertCmd, conn);
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.Parameters.AddWithValue("#Album", txtAlbum.Text);
myCommand.Parameters.Add("#id", SqlDbType.Int).Direction = ParameterDirection.Output;
myCommand.ExecuteNonQuery();
int id = (int)myCommand.Parameters["#id"].Value;
}
Using above code you can insert a date from TextBox and also get last inserted record ID as an output variable as per your requirement.
Thanks .

Unable to get data from stored procedure

I'm trying to hit the stored procedure from C# code but always get the result == -1. I don't know where I went wrong. I have searched a lot but didn't' find any solution. Please have a look into my code snippet and guide me what I'm doing wrong.
Thanks in advance.
C# code:
using (SqlConnection connection = new SqlConnection(getConnectionString()))
using (SqlCommand command = new SqlCommand())
{
Int32 rowsAffected;
command.CommandText = "SP_LOGIN_GETUSERBYNAME";
command.CommandType = CommandType.StoredProcedure;
// command.Parameters.Add(new SqlParameter("#Email", userObj.email));
// command.Parameters.Add("#Email", SqlDbType.VarChar).Value = userObj.email.Trim();
command.Parameters.AddWithValue("#Email", userObj.email.ToString());
command.Connection = connection;
connection.Open();
rowsAffected = command.ExecuteNonQuery();
connection.Close();
return rowsAffected;
}
Connection string:
return "Data Source=MUNEEB-PC;Initial Catalog=HRPayRoll;User ID=sa; Password=sa";
Stored procedure code:
CREATE PROCEDURE SP_LOGIN_GETUSERBYNAME
#Email varchar(50)
AS
SELECT *
FROM [User]
WHERE Email = #Email
GO
From ExecuteNonQuery doc;
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
Since your command is SELECT, it is too normal to get -1 as a return value.
If you wanna reach your results, you can use ExecuteReader method instead.
var reader = command.ExecuteReader();
while (reader.Read())
{
// This will iterate your results line by line and
// You can get columns with zero-based values like reader[0], reader[1] or
// can use GetXXX methods of it like GetString(0) or GetInt32(1) etc.
}

SQL Server database last_rowID

I have a C# app with have to use SQL Server database with 1 table (All_Data) and 5 columns (ID, Name, Surename, Age,Location)
Before inserting a new row how can I find out or get the value of the last ID in the table
I have a following code but it,a not work well
string query = "SELECT MAX(ID) FROM All_Data";
SqlCommand comSelect;
comSelect = new SqlCommand(query, connection);
int ID = (int)comSelect.ExecuteScalar();
ERROR message:
ExecuteScalar: Connection property has not been initialized
Please help me
First, from your code it is not clear what is the value of the variable connection.
From the error message it seems that you don't have initialized this variable and thus you get the error. (connection = new SqlConnection(....);)
However, this is not the correct way to handle this scenario.
You need to make the ID column an IDENTITY column and then don't try to retrieve its value before executing any INSERT.
An IDENTITY column receives its value directly from the database when there is a new record to insert. And letting the database code work on this data it is the best option if you want to be safe from concurrency issues.
If you need to retrieve the ID value after an INSERT query because you need it as a Foreign Key in other tables or for your own code, then you could simply use the T-SQL command
SELECT SCOPE_IDENTITY()
For example, suppose you have to insert a record in that table, and you want to know the IDENTITY value assigned to the ID column
string query = #"INSERT INTO All_Data(Name,Surename,Age,Location)
VALUES(#name, #surname, #age, #loc);
SELECT SCOPE_IDENTITY()";
using(SqlConnection connection = new SqlConnection(connectionString))
using(SqlCommand cmd = new SqlCommand(query, connection))
{
connection.Open();
cmd.Parameters.AddWithValue("#name", yourNameValue);
.... other parameters ...
int newID = Convert.ToInt32(cmd.ExecuteScalar());
}
As you can see, this code doesn't try to pass a value for the ID column. It pass just the other fields with a parameterized query. But at the end of the first query there is a call to SELECT SCOPE_IDENTITY() and this returns whatever value the database has assigned to the column ID (of course you should have set the IDENTITY property on the field).
This will work correctly in multiuser and concurrent scenario
The error fires when the command doesn't have a connection. Please check connection is open.
Error saysExecuteScalar: Connectio property has not been initialized
double Check your connection string whether it is defined properly. You can check here to know how to define connection string.
you have not opened connection so open it before use :
comSelect = new SqlCommand(query, connection);
connection.Open();
int ID = (int)comSelect.ExecuteScalar();
connection.Close();

How can i get the ##IDENTITY returned from a INSERT from MySQL (2008) using C# [duplicate]

Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}

Return value from SQL Server Insert command using c#

Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}

Categories