Checking for Primary Key assignment - c#

I have a web application that writes to several databases for tracking employee change requests. I am running into a problem with entering in a new employee. They are first written to main Employee database before their access information is written to the other databases with EMP_ID being the primary key. When it goes to write to the other databases EMP_ID has been generated yet so it is getting entered in as 0.
To resolve this I was trying to loop and check the EMP_ID value until a value is generated but I continue to get stuck in a loop because the query returns back that no value was found.
while (int.Parse(empIDChecker) == 0)
{
dbConnection.Open();
validateIDSQLString = "SELECT EMP_ID FROM EMPLOYEE_TABLE WHERE FIRST_NAME = '" + firstNameTextBox.Text.Trim() + "' AND LAST_NAME = '" + lastNameTextBox.Text.Trim() + "'";
SqlCommand updateSQLCmd = new SqlCommand(validateIDSQLString, dbConnection);
SqlDataReader getRecords = updateSQLCmd.ExecuteReader();
try
{
empIDChecker = getRecords["EMP_ID"].ToString();
}
catch
{
empIDChecker = "0";
}
getRecords.Close();
dbConnection.Close();
}

OK, so if your insert sproc looks something like:
sp_InsertEmp
...
INSERT INTO Emp(Name, etc...)
VALUES ('Paul', etc...)
SELECT SCOPE_IDENTITY() AS EMP_ID
GO
And in your code:
SqlCommand insertCmd = new SqlCommand("sp_InsertEmp", dbConnection);
... Add parameters here and set type to StoredProcedure
SqlDataReader dr= insertCmd.ExecuteReader();
int newId;
if (dr.Read())
{
newId = dr.GetInteger(0);
}

you can use
SELECT IDENT_CURRENT(‘tablename’)
This will give you the last inserted auto increment ID of the table, you can use that to insert in other table
Check this link as well http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

Related

Update and delete rows from an access database don't work in a windows forms app

i create a database with access and used this database in an Windows forms app.
I can select and insert rows from the database but i can't delete and update the database.
I used the following code. The first part works, the second doesen't.
if (!string.IsNullOrEmpty(this.txb_Box.Text) && !string.IsNullOrEmpty(this.txb_Teil.Text))
{
this.select = "SELECT * FROM Lagerhaltung WHERE BoxNr='"+ this.txb_Box.Text+"' AND Reklamation='"+this.txb_Teil+"'";
DbCommand command2 = connection2.CreateCommand();
command2.CommandText = this.select;
DbDataReader reader2 = command2.ExecuteReader();
if(!reader2.HasRows)
{
this.select = "INSERT INTO Lagerhaltung ( BoxNr, Reklamation, EingelagertAm, Artikelnr) VALUES ('" + this.txb_Box + "','"+this.txb_Teil.Text+"','" + this.lbl_Datum.Text + "', 'Test')";
}
}
"UPDATE Lagerhaltung SET AusgelagertAm='"+this.lbl_Datum.Text+"', Erledigt= True WHERE id like '"+data.id+"'";
"DELETE FROM Lagerhaltung WHERE id like '1'";
Can someone help me?
Best regards
JuRi-2020
I find the mistake. I don't activate the command with
command.ExecuteNonQuery();
that's why nothing happened.

Getting a String from a value in Mysql in C#

i have the following table in MySql :
ID Name
1 Google
2 Yahoo
3 Facebook
4 Whatever
I have a textfield that when someone writes something and presses a button it stores this value in a string. This string is the Name of the above table. Then i have my code about selecting the id referred to that name. Ex, if the user enters Facebook i will find that the ID = 3. this is the code :
public bool FindCompanyID(string companyName)
{
return ExecQuery("select id from companies where name=#name",
cmd =>
{
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
return cmd;
});
}
I want someone to show me a sample of code about the following : Saving to a string the " id " . if the ID in the database = 2 i want to make a
int Company_Number_ID
that i will use. How can i get the string to read the specified value from the database?
I am guessing your return type is bool to check whether the DDL statements were executed successfully.
MySqlCommand cmd = dbConn.CreateCommand();
cmd.CommandText = "SELECT id from companies WHERE name ='" + companyName + "'";
try
{
dbConn.Open();
Company_Number_ID = (Int32)cmd.ExecuteScalar();
} catch (Exception e) {
//Exception occured. Handle it here
}
Note: cmd.Parameters.AddWithValue("#companyName",companyName).
this is more secure
Edit: As pointed out in the comment by user3185569 , ExecuteScalar is better if you are sure it'll return only one row. But since no such information was provided. I did not consider that.
You can use ExecuteScalar directly like this.
Company_Number_ID = (Int32)cmd.ExecuteScalar();

Reduce the number of SqlCommands required to send information to three tables

I have the following code:
command = new SqlCommand("SELECT UserId from Users WHERE Username = N'" + userName + " AND " + userPassword + "= N'" + userPassword + "AND AccountStatus = 0");
command.CommandType = System.Data.CommandType.Text;
command.Connection = conn;
int uid = (int)command.ExecuteScalar();
if(uid > 0)
{
command = new SqlCommand("UPDATE IsOnline =" + true + " WHERE UserId = 'N" + uid);
command.ExecuteNonQuery();
command = new SqlCommand("INSERT INTO LogonHistory OUTPUT LogonHistoryId VALUES(NULL," + uid + "," + DateTime.Now + ")");
int id = (int) command.ExecuteNonQuery();
command = new SqlCommand("INSERT INTO UsersLogOnHistory VALUES(NULL," + uid + "," + id + ")");
command.ExecuteNonQuery();
IsAuthorised = true;
SendMessage(ID, ServerCommands.Success, IsAuthorised.ToString());
}
else
{
// User does not exist
SendMessage(ID, ServerCommands.Failed, IsAuthorised.ToString());
}
The first SQLCommand executed checks to see if the Username and password are correct and if their account is not suspended. It then (should) return the Row ID.
If the RowID > 0 then we have a valid logon.
Next SQLCommand updates the IsOnline status within the same table
The next SQLCommand Inserts into the LogonHistory the Users ID, and the DateTime. Now setting id with the Row Id
finally the SQLCommand is executed to insert the RowId we got from the last command and the User's Id into UserLogOnHistory. (which allows us to do a quick look up) - theoretically for updating the LogonHistory for when this user logs off.
I now realise that this is a mess!
So to the Questions:
How do I get the RowId of the table affected by the last command.
How can I optimise the queries to reduce the number of SQLCommands executed - or does this seem reasonable.
You can issue multiple TSQL commands in one batch by simply... including multiple TSQL commands. To be thorough, you should delimit them with ;, but in most (not all) cases, that is optional and it will work without.
To get the most recently inserted identity value; SCOPE_IDENTITY(). This only works for INSERT, and only with there is an IDENTITY column. In all other cases: OUTPUT.
Note; you should parameterize, but consider:
UPDATE IsOnline = 1 WHERE UserId = #uid;
DECLARE #lhid int
INSERT INTO LogonHistory (explict columns here)
VALUES(NULL,#uid, GETUTCDATE());
SET #lhid = SCOPE_IDENTITY();
INSERT INTO UsersLogOnHistory (explicit columns here)
VALUES(NULL,#uid, #lhid);
Note that you could also do the last bits with an INSERT trigger on LogonHistory, or via OUTPUT.
The number of round trips here: 1
If it was me i would put all that logic in a stored procedure, it's more easy to test and makes for better decoupling.
CREATE PROC logon
#username NVARCHAR(MAX)
, #password NVARCHAR(MAX)
, #IsAuthorized BIT OUTPUT
AS
BEGIN
SELECT #UID = UserId
FROM Users
WHERE Username = #username
AND userPasswordHash = CHECKSUM(#password);
UPDATE Users
SET IsOnline = 1
WHERE UserId = #UID;
INSERT INTO LogonHistory
VALUES(NULL,#UID,GETDATE());
INSERT INTO UsersLogOnHistory
VALUES(NULL,#UID,SCOPE_IDENTITY());
IF #UID IS NOT NULL
SET #IsAuthorized = 1;
ELSE
SET #IsAuthorized = 0;
END;
PS: please be considered for you colleagues privacy and hash their passwords.

Inserting the max value of one comlumn from one table to another table

I am updating a database with a new registered user. they will then be given a userid. I want to use that number when updating there location in another table. but i dont know what the user id will be. (it is autoincrement number) So i was thinkning i would update the first table. And then select the maximum user id and insert that id as the location user id in the other table but I cant get it to work.
Here is the code.
String StrSQL = "INSERT INTO Fastelejer (Fornavn,Efternavn) VALUES ('" + fornavn + "','" +
Efternavn + "')";
OleDbCommand InsertCommand = new OleDbCommand(StrSQL, conn);
InsertCommand.ExecuteNonQuery();
StrSQL = "INSERT INTO Bådpladser (Fastelejerid) SELECT MAX (Fastelejerid) FROM
StrSQL = "INSERT INTO Bådpladser (Fastelejerid) SELECT MAX (Fastelejerid)FROM
Fastelejer WHERE Pladsnummer = " + Pladsnummer;
The pladsnummer represents the input for their location. So the registration should put the user id into the location that is chosen.
In MS Access, "autoincrement" is usually called "identity". You can use the special ##IDENTITY variable to retrieve the ID of the last inserted identity column. Once you know the new ID, you can add it as a parameter in the second insert, like:
command.CommandText = "INSERT Table1 (...) values (...); SELECT ##IDENTITY";
var identity = (int) command.ExecuteScalar();
command.CommandText = "INSERT Table2 (user_id, ...) VALUES (#user_id, ...)";
command.Parameters.AddWithValue("#user_id", identity);
command.ExecuteNonQuery();

SQLite Last Insert Rowid Does Not Work

I found several examples of how to get the last inserted row id from an sql insert call to my SQLite database, but my script threw this error:
SQLiteException
Message = "SQLite error\r\nnear \")\": syntax error"
InnerException
NULL
Below is the SQL text I sent in and how I used it. Obviously, I misunderstood something. Could someone help me out here?
I am trying to return the ID number that was just inserted.
private static int Save(Dates date, SQLiteConnection con) {
// REF: http://www.sqlite.org/c3ref/last_insert_rowid.html
int result = 0;
string sql = "INSERT INTO Dates1 " +
"(ID, TaskID, Last1) " +
"VALUES " +
"((SELECT MAX(ID) FROM Dates1)+1, #TaskID, #Last); " +
"SELECT sqlite3_last_insert_rowid(sqlite3*);";
using (SQLiteCommand cmd = new SQLiteCommand(sql, con)) {
cmd.Parameters.AddWithValue(Dates.AT_TASK, date.TaskID);
cmd.Parameters.AddWithValue(Dates.AT_LAST, date.Last.ToShortDateString());
cmd.CommandText = Dates.SQL_INSERT;
try {
result = cmd.ExecuteNonQuery();
} catch (SQLiteException err) {
result = -1;
LogError("Save(Dates, SQLiteConnection)", err);
}
}
return result;
}
FYI: I have set up the table so that ID is supposed to be auto generated using the Create SQL below, but the table only stores -1 for the ID values unless I manually insert it.
public const string SQL_CREATE = "CREATE TABLE Dates1 " +
"(ID INTEGER PRIMARY KEY AUTOINCREMENT, TaskID INTEGER, Last1 TEXT);";
To quote from the SQLite documentation:
last_insert_rowid() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. The last_insert_rowid() SQL function is a wrapper around the sqlite3_last_insert_rowid() C/C++ interface function.
So you need to change your statement to:
"SELECT last_insert_rowid();"
because what you did was to try and call the C API function.

Categories