Get auto_increment id from table - c#

I have this code:
string conStr = ConfigurationManager.ConnectionStrings["BackgammonGame"].ConnectionString;
SqlConnection con = new SqlConnection(conStr);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = ("INSERT INTO Game (playerA, playerB) OUTPUT INSERTED.gameID VALUES (#playerA, #playerB)");
cmd.Parameters.Add("#playerA", SqlDbType.NVarChar).Value = firstPlayer;
cmd.Parameters.Add("#playerB", SqlDbType.NVarChar).Value = secondPlayer;
cmd.ExecuteNonQuery();
int id = (int)cmd.ExecuteScalar();
con.Close();
When I insert into this table, I have an auto_increment int primary key column called gameID, and I declared in the sql statement that I want the gameID in output.
my problem is that when I write this line in the code: int id = (int)cmd.ExecuteScalar(); the inserted parameters apear twice in the table (2 rows with the same info.), but when I delete it it's ok.
I need this row so I can use this id in other table.

Change your command text with this and try
cmd.CommandText = ("INSERT INTO Game (playerA, playerB) VALUES (#playerA,#playerB);
SELECT SCOPE_IDENTITY()");
SCOPE IDENTITY returns the identity value of last inserted row. Hence that will returns the identity filed of the inserted row using the insert query
EDIT
You are executing the query two times
cmd.ExecuteNonQuery(); // Avoid this
int id = (int)cmd.ExecuteScalar();// This is enough
In both case your query gets executed and it cause insertion twice.
ExecuteNonQuery() will execute the insert query and will returns the number of rows affected.
Where as ExecuteScalar() will return the result of the select scope_identity() staement which is the identity column of the inserted row.
Here is your code
con.Open();
cmd.CommandText = ("INSERT INTO Game (playerA, playerB) VALUES (#playerA,#playerB);
SELECT SCOPE_IDENTITY()");
cmd.Parameters.Add("#playerA", SqlDbType.NVarChar).Value = firstPlayer;
cmd.Parameters.Add("#playerB", SqlDbType.NVarChar).Value = secondPlayer;
int id = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();

Modify your command like this
INSERT INTO YourTable(val1, val2, val3 ...)
VALUES(#val1, #val2, #val3...)
SELECT SCOPE_IDENTITY()
But i personally prefer to write a stored procedure and return the primary key as an output parameter of that sp.

Related

How to insert data into two tabels?

I have two tables FILM(Id, Title, Director, Year, Category) and Record(Id, Film_id)
Id from FILM table is used as a foreign key as Film_id in Record table.
I want to insert data at the same time date into both tables. How construct a sql query with INSERT?
using (var connection = new MySqlConnection(constring))
{
connection.Open();
using (var cmdDataBase = connection.CreateCommand())
{
cmdDataBase.CommandText = "INSERT INTO film(Title, Director, Year, Category) VALUES (#Title, #Director, #Year, #Category) ";
cmdDataBase.Parameters.Add(new MySqlParameter("#Title", fm.Title));
cmdDataBase.Parameters.Add(new MySqlParameter("#Director", fm.Director));
cmdDataBase.Parameters.Add(new MySqlParameter("#Year", fm.Year));
cmdDataBase.Parameters.Add(new MySqlParameter("#Category",n));
cmdDataBase.ExecuteNonQuery();
}
}
You get the last auto-generated ID with LAST_INSERT_ID(). Then, you'd use a transaction, because you don't want to insert a parent record, if you can't also insert the child record, or so I understand.
This is it more or less. You should add error handling (try, catch) of course.
// Start transaction
MySqlTransaction transaction = connection.BeginTransaction();
MySqlCommand command = new MySqlCommand();
command.Connection = connection;
command.Transaction = transaction;
// Parent record
command.CommandText = "INSERT INTO film(Title, Director, Year, Category) VALUES (#Title, #Director, #Year, #Category) ";
command.Parameters.Add(new MySqlParameter("#Title", fm.Title));
command.Parameters.Add(new MySqlParameter("#Director", fm.Director));
command.Parameters.Add(new MySqlParameter("#Year", fm.Year));
command.Parameters.Add(new MySqlParameter("#Category",n));
command.ExecuteNonQuery();
// Child record
command.CommandText = "INSERT INTO record (Film_id) VALUES (LAST_INSERT_ID())";
command.ExecuteNonQuery();
// Commit inserts
transaction.Commit();
You need to do it in sequence. First, add record to your main table Film, then other table Record. Check below:
INSERT INTO Film(Title, Director, Year, Category)
VALUES('Title', 'DirectorName', 1990, 'Action');
--Assuming ID for Record table is AUTO_INCREMENT column
INSERT INTO Record(Film_id)
VALUES ((SELECT id FROM Film WHERE Title='Title' and Director='Director'));
Also, LAST_INSERT_ID() can be used:
INSERT INTO Film
...
INSERT INTO Record
...
film_id = LAST_INSERT_ID()
Ref: Mysql: How to insert values in a table which has a foreign key
If you are using MySQL try to add ;return LAST_INSERT_ID(); at the end of you query and add return parameter as below.
var returnVal = cmdDataBase.Parameters.Add("#ReturnVal", SqlDbType.Int);
returnVal.Direction = ParameterDirection.ReturnValue;
After cmdDataBase.ExecuteNonQuery(); extract id from returnVal
var id = returnParameter.Value;
After that you can use id to perform the second insert.

C# Insert Value Foreign Key

I have 2 tables which are tableCustomerLogin and tableCustomerRegister. There is Foreign Key for the tableCustomerLogin i.e. cust_id.
In the tableCustomerLogin, I have tableCustomerLogin
cust_login_id
cust_id
cust_email
cust_username
cust_password
and for tableCustomerRegister,
tableCustomerRegister
cust_id
cust_fullname
cust_username
cust_email
cust_password
cust_mobile_number
cust_image
cust_address1
cust_address2
cust_city
cust_postcode
cust_create_acc_time
When customer register, the data will store in the tableCustomerRegister. How to make it register in the tableCustomerLogin?
string sql = #"INSERT INTO tableCustomerRegister VALUES (#cust_fullname, #cust_username, #cust_email, #password, #cust_mobile_phone, #cust_address1, #cust_address2, #cust_image, #cust_city, #cust_state, #cust_postcode, #cust_create_acc_time, #role, #enabled)";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#cust_fullname", txtFirstName.Text + " " + txtLastName.Text);
cmd.Parameters.AddWithValue("#cust_username", txtUsername.Text);
cmd.Parameters.AddWithValue("#cust_email", txtEmail.Text);
cmd.Parameters.AddWithValue("#password", passwordhash);
cmd.Parameters.AddWithValue("#cust_mobile_phone", txtMobilePhone.Text);
cmd.Parameters.AddWithValue("#cust_address1", txtAddress1.Text);
cmd.Parameters.AddWithValue("#cust_address2", txtAddress2.Text);
cmd.Parameters.AddWithValue("#cust_image", txtProfilePicture.Text);
cmd.Parameters.AddWithValue("#cust_city", ICityString());
cmd.Parameters.AddWithValue("#cust_state", ddState.SelectedValue.ToString());
cmd.Parameters.AddWithValue("#cust_postcode", txtPostcode.Text);
cmd.Parameters.AddWithValue("#cust_create_acc_time", DateTime.Now);
cmd.Parameters.AddWithValue("#role", "user");
cmd.Parameters.AddWithValue("#enabled", enabled);
try
{
conn.Open();
cmd.ExecuteNonQuery();
lblStatus.Text = "Status: Data successfully saved.";
}
well, first of all you need to change your query
string sql = #"INSERT INTO tableCustomerRegister OUTPUT INSERTED.cust_id VALUES (#cust_fullname, #cust_username, #cust_email, #password, #cust_mobile_phone, #cust_address1, #cust_address2, #cust_image, #cust_city, #cust_state, #cust_postcode, #cust_create_acc_time, #role, #enabled)";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("#cust_fullname", txtFirstName.Text + " " + txtLastName.Text);
cmd.Parameters.AddWithValue("#cust_username", txtUsername.Text);
//so on (all your parameters)
var custid = (int)cmd.ExecuteScalar()
ExecuteScalar return int, in this case it will return cust_id as your query have OUTPUT INSERTED.cust_id. Now You have your inserted cust_id saved in tableCustomerRegister. Now all you need to do just write another query for save data into your tableCustomerLogin with foreign key cust_id. like this,
string Sql2 = "INSERT INTO tableCustomerLogin (column_names) VALUES (parameters values)";
SqlCommand cmd = new SqlCommand(sq2, conn);
cmd.Parameters.AddWithValue("#cust_id",custid); //as foreign key
//all other Parameters
You can first insert a tableCustomerRegister record and then insert another data the tableCustomerLogin table. You would be better do this in the transaction block.
The other way , You can add a trigger to the tableCustomerLogin table.
CREATE TRIGGER trg_tableCustReg ON tableCustomerRegister
FOR INSERT
AS
/*
* if CustLoginID is a identity , no dont need to add
*/
INSERT INTO tableCustomerLogin
(cust_login_id, cust_id, cust_email, cust_username, cust_password)
Select
'CustLoginID',
cust_id ,
cust_email,
cust_username,
user_password
FROM inserted
go
Probably the best solution is to follow the DRY principle, Dont Repeat Yourself.
I think that you can store all information in a single table customer_table for example and then retrive the necessary data with a more simple logic from only this table.
Instead, if you want to stay on your actual data structure, simply add new insert statement after firstseparate by semicolon
how to insert data into multiple tables at once
there are two different way. you shold use SCOPE_IDENTITY
string sql = #"INSERT INTO tableCustomerRegister VALUES (#cust_fullname, #cust_username, #cust_email, #password, #cust_mobile_phone, #cust_address1, #cust_address2, #cust_image, #cust_city, #cust_state, #cust_postcode, #cust_create_acc_time, #role, #enabled) SELECT SCOPE_IDENTITY()";
SCOPE_IDENTITY Returns the last identity value inserted into an
identity column in the same scope
var newId= cmd.ExecuteScaler();
newId created new Primary Key ID for you cust_id
you have this ID(cust_id) and you can register in the Login table.
INSERT INTO tableCustomerLogin (cust_login_id,**cust_id**,cust_email,cust_username,cust_password)
cust_id = newId
If Cust_id is auto-created in the tableCustomerRegister table, then you can save the same id in the tableCustomerLogin table (cust_id). then only your foreign Key relation work.
try
{
conn.Open();
cmd.ExecuteNonQuery();
SqlCommand get_custid_cmd = new SqlCommand("select ##identity", conn);
int cust_id = Convert.ToInt32(get_custid_cmd.ExecuteScalar());
string sql_insert = #"INSERT INTO tableCustomerLogin VALUES (#cust_id, #cust_username, #cust_email, #password)";
SqlCommand cmd_insert = new SqlCommand(sql_insert, conn);
cmd_insert.Parameters.AddWithValue("#cust_id",cust_id);
cmd_insert.Parameters.AddWithValue("#cust_username", txtUsername.Text);
cmd_insert.Parameters.AddWithValue("#cust_email", txtEmail.Text);
cmd_insert.Parameters.AddWithValue("#password", passwordhash);
cmd_insert.ExecuteNonQuery();
lblStatus.Text = "Status: Data successfully saved.";
}

SCOPE_IDENTITY() returns thousand number

I have an insert query like the below. However, scopeIdentity does not return 42, it returns 1042.
This is the SQL Server table:
My code:
int masterId = 0;
using (SqlConnection cmd = new SqlConnection(connString))
{
using (SqlCommand conn = cmd.CreateCommand())
{
conn.CommandText = "INSERT INTO[MasterReportData]([ReportName],[CaseList],[EmployeeId],[datetime]) VALUES(#reportName, #caseList, #employeeId, #datetime) SET #ID = SCOPE_IDENTITY()";
conn.Parameters.Add("#reportName", SqlDbType.VarChar).Value = reportName;
conn.Parameters.Add("#caseList", SqlDbType.VarChar).Value = caseList;
conn.Parameters.Add("#employeeId", SqlDbType.Char).Value = employeeId;
conn.Parameters.Add("#datetime", SqlDbType.DateTime).Value = datetime;
conn.Parameters.Add("#ID", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Open();
conn.ExecuteNonQuery();
masterId = Convert.ToInt32(conn.Parameters["#ID"].Value);
cmd.Close();
}
}
Have a look at https://learn.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql
The description says:
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, if two statements are in the same stored procedure, function, or batch, they are in the same scope.
In words: it Returns the last id and not the next to use. Therefore you can't use the INSERT command like that. What you can do is:
Configure your ID as auto-increment id. Then run the INSERT command and run SELECT SCOPE_IDENTITY() afterwards to find out which ID was used.

Insert into multiple tables using INSERT_IDENTITY - ADO.Net

I want to INSERT records in multiple tables with ADO.NET.
I want to INSERT a new record into a table called Professionals. It has a foreign key mapped to a different table.
tables:
Example:
cmd.CommandText = "insert T_Name select (Name.T_Name,Date.T_Name,DId.Date) values (#N,GETDATE(),???)from T_Name inner join Date ON Date.DId=T_Name.DId; ";
cmd.Parameters.AddWithValue("#N", txt_Name.Text);
OR
...
How can I add values into these tables at one time?
After add insert sql for first table
SELECT SCOPE_IDENTITY();
then you get last inserted id. You can use second sql parameters.
Example:
var dateNow = DateTime.Now;
var cmd = new SqlCommand("INSERT INTO Date (Date) VALUES (#Date);SELECT SCOPE_IDENTITY();", cnn);
cmd.Parameters.AddWithValue("#Date", dateNow);
var insertedId = cmd.ExecuteScalar();
cmd = new SqlCommand("INSERT INTO T_Name (Name,Date,DId) VALUES (#Name,#Date,#DId);", cnn);
cmd.Parameters.AddWithValue("#Name", "Test");
cmd.Parameters.AddWithValue("#Date", dateNow);
cmd.Parameters.AddWithValue("#DId", insertedId);
cmd.ExecuteNonQuery(); //or ExecuteScalar() for get last insertedId

Convert ID to Int and save to datatable

I have been trying to add the Customer_ID from the Customer table to Customer_ID in Customer_Ship table. I keep running into the Customer_ID not converting to Int properly. It's possible that I am not actually getting the new row added to Customer_Ship table first. Your help is greatly appreciated and many thanks in advance.
if (customer_ID == "")
{
string SQL = "INSERT INTO Customer (Customer_Name) VALUES (#customer_Name); SELECT Customer_ID FROM Customer WHERE Customer_ID = SCOPE_IDENTITY();";
SqlCommand sqlCommand = new SqlCommand(SQL, sqlConnection);
sqlCommand.Parameters.Add("#customer_Name", SqlDbType.VarChar, 100).Value = customer_Name;
sqlConnection.Open();
int customer_Id = (int)sqlCommand.ExecuteScalar();
SQL = "INSERT INTO Customer_Ship (Customer_ID) VALUES (#customer_Id)";
sqlCommand = new SqlCommand(SQL, sqlConnection);
sqlCommand.Parameters.AddwithValue("#customer_Id", customer_Id);
sqlCommand.ExecuteNonQuery();
sqlConnection.Close();
}
Two mistakes I see:
you should be just returning SCOPE_IDENTITY - you can simplify your first INSERT statement to read:
INSERT INTO Customer (Customer_Name) VALUES (#customer_Name); SELECT SCOPE_IDENTITY();";
This will return the newly inserted Customer_ID identity value from the Customer table - no need to do this complicated SELECT that you had in your question
You need to call .ExecuteScalar() right from the beginning - don't call .ExecuteNonQuery() first and then ExecuteScalar() - that'll execute the statement twice - just use:
using(SqlCommand sqlCommand = new SqlCommand(SQL, sqlConnection))
{
sqlCommand.Parameters.Add("#customer_Name", SqlDbType.VarChar, 100).Value = customer_Name;
sqlConnection.Open();
int customer_Id = (int)sqlCommand.ExecuteScalar();
sqlConnection.Close();
}
That'll insert the values into Customer and return the newly created Customer_ID as the return value into customer_id (which already is an Int) from .ExecuteScalar(). You can then use this int value to insert into the Customer_Ship table - no conversion necessary - this already is an int
The possible reason for not converting the value is you are trying to convert an empty string(customer_ID : Refer Line :#1 of your code) and not "customer_Id " what you are fetching from the database .

Categories

Resources