Cannot update id - id not updatable - c#

I try to update my info data (in access database) on employee table, but I get this error that says cannot update id - id not updatable
Lets say I have this employee
ID : 1
Name : Mark
LastName : Jonhson
Age : 33
I write update statement, in case I want to change his info in future, ...let's say
ID : 1
Name : Mark
LastName : Markson
Age: 34
My code What did I do wrong and how do I update/edit my data
private void button2_Click_2(object sender, EventArgs e)
{
try
{
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = myConnection;
cmd.CommandText = "Update Employee set ID = #ID, Name = #Name, LastName = #LastName, User_name = #User_name, Password = #Password, E_mail = #E_mail, Address = #Address";
cmd.Parameters.Add("#ID", ID.Text);
cmd.Parameters.Add("#Name", name.Text);
cmd.Parameters.Add("#LastName", lastName.Text);
cmd.Parameters.Add("#User_name", userName.Text);
cmd.Parameters.Add("#Password", pass.Text);
cmd.Parameters.Add("#E_mail", eMail.Text);
cmd.Parameters.Add("#Address", address.Text);
myConnection.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("User updated!");
myConncetion.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

You should add a WHERE to your command text.If you don't it,all of your records will be change.I think you want this:
cmd.CommandText = "Update Employee SET Name = #Name, LastName = #LastName, User_name = #User_name, Password = #Password, E_mail = #E_mail, Address = #Address WHERE ID = #ID";

I suppose that your "ID" is not just a piece of data, but the table primary key too. In that case you should never update that.
The primary key is meant to be immutable, not only because it uniquely identifies a record in the DB, also all other tables will reference this column though foreign keys, which will either break or leave orphaned rows everywhere. Additionally, what's the purpose of updating it? The user is not even aware of its existence, since it's only part of the internal DB structure that keeps integrity, nothing more.
In short, don't try it.
If you really want to update it, the column should not be autogenerated, as the DB engine most likely will catch your error and prevent it.

Chances are, ID is an auto-generated primary key in the database. You cannot update that.
Actually, your UPDATE statement would update all records in the table, since it is lacking a WHERE clause. This is very dangerous. You should specify the record you want to update in your WHERE clause, and when possible, reference it via the primary key:
UPDATE Employee Name = #Name, LastName = #LastName, User_name = #User_name, Password = #Password, E_mail = #E_mail, Address = #Address
WHERE Id = #Id;

Related

Error in Updating a Record

Hello Everyone I'm new in here. I am currently making an asp.net project monitoring module. At this moment I am in the process of editing the project form and adding resources to the selected task in a project.
I'm having a problem in saving the record. Everytime I save the record it says
"Column name or number of supplied values does not match table
definition."
In my ProjectTasks Table I have RefNo(PK), TaskID(FK), Name and Description
Name - refers to the Task Name
Description - refers to the Task Description
What I want to happen is that my Resource Tables TaskID(FK) will be updated when I clicked the save button. As of now when I add a Resource from a task the TaskID = 0.
protected void btnSave_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "INSERT INTO ProjectTasks VALUES (#Name, #Description); " +
"SELECT TOP 1 TaskID FROM ProjectTasks ORDER BY TaskID DESC;";
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#Description", txtDescription.Text);
int taskID = (int)cmd.ExecuteScalar();
con.Close();
con.Open();
cmd.CommandText = #"UPDATE Resource_Materials SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Equipments SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Vehicles SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Contractors SET TaskID=#TaskID WHERE TaskID=0;";
cmd.Parameters.AddWithValue("#TaskID", taskID);
cmd.ExecuteNonQuery();
con.Close();
Helper.AddLog("1", "Add", "Assigned Resources to Task");
Response.Redirect("~/Projects/Default.aspx");
}
Sorry about my grammar I'm just a student.
You said
ProjectTasks Table I have RefNo(PK), TaskID(FK), Name and Description
In such case, your INSERT query should look like below instead, specify the exact column name you are trying to insert values and as well you are missing TaskID(FK) column in your current insert query
INSERT INTO ProjectTasks(TaskID, Name, Description)
VALUES (#TaskID, #Name, #Description);
In an insert statement, we need to supply the column names when we don't want to specify values for all columns. If we don't do this we need so supply values for all columns.
In your case, you just want to provide values for Name and Description so you can do something like:
INSERT INTO ProjectTasks(Name, Description) VALUES (#Name, #Description);
Your logic is misleading..
Your ProjectTasks has 4 columns but you try to insert 2 column value in your insert statement without declaring them after your table name as ProjectTasks (Name, Description).
But this still generate a problem because your first column is PK and second one is FK. Since FK can be null but PK can't be null as far as I know, that's why you need to re-think your inserting logic.
But even if you fix it, your code still has a problem. Since you set a new string to your CommandText property, your #Name and #Description parameters were still belongs on your cmd object. That's why on ExecuteNonQuery line, your cmd will have 3 parameters as #Name, #Description and #TaskID but your command has only 1 parameter. As you can see, you will get an error such as; the parameter you supplied and command doesn't match or something. In such a case, you need to Clear() your parameters before you set new CommandText or generate a new SqlCommand object as cmd = new SqlCommand()
Also use using statement to dispose your connection and commands automatically instead of calling .Close() or .Dispose() methods manually.
And don't use AddWithValue method anymore. It may generate unexpected results sometimes. Use Add method overloads to specify your parameter type and it's size.
Solved it by removing ExecuteScalar and by replacing INSERT statement into UPDATE statement instead.
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "UPDATE ProjectTasks SET Name=#Name, Description=#Description " +
"WHERE TaskID=#TaskID; " +
"SELECT TOP 1 TaskID FROM ProjectTasks ORDER BY TaskID DESC;";
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#Description", txtDescription.Text);
cmd.Parameters.AddWithValue("#TaskID", Request.QueryString["ID"].ToString());
cmd.CommandText = #"UPDATE Resource_Materials SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Equipments SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Vehicles SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Contractors SET TaskID=#TaskID WHERE TaskID=0;";
cmd.ExecuteNonQuery();
con.Close();
Helper.AddLog("1", "Add", "Assigned Resources to Task");
Response.Redirect("~/Projects/Default.aspx");

Strange behaviour on Update query with C# and Access

I am facing a strange problem, When i try to run the below code to update a record in access db.
string updateQuery = "UPDATE Employee SET Employee_name = #name, Employee_desig = #designation, Employee_salary = #salary, Employee_phone = #phone, Employee_mobile = #mobile, Employee_email = #email, Employee_status = #status WHERE (((Employee_id)=#empId));";
dbCmd.CommandText = updateQuery;
dbCmd.Parameters.AddWithValue("#designation", designation);
dbCmd.Parameters.AddWithValue("#email", email);
dbCmd.Parameters.AddWithValue("#mobile", mobile);
dbCmd.Parameters.AddWithValue("#name", name);
dbCmd.Parameters.AddWithValue("#phone", phone);
dbCmd.Parameters.AddWithValue("#salary", salary);
dbCmd.Parameters.AddWithValue("#status", status);
dbCmd.Parameters.AddWithValue("#empId", employeeId);
dbCmd.ExecuteNonQuery();
ExecuteNonQuery() return 1. But when i check in db, inputs are updated in different columns.
input values are
designation="Manager"
email="e"
mobile="2"
name="n"
phone="1"
salary=10.0
status="Active"
employeeId=3
any help will be appreciated.
In the context of ACE OLEDB the parameter names are ignored and the parameters must be defined in the same order that they appear in the SQL statement.

Cannot insert the value NULL into column 'UserId', table

I encounter this error when trying to insert the comments user edited under my UPDATE SQL statement. As my UserId is an uniqueIdentifier, I do not really know how to solve this error.
The error shows:
Cannot insert the value NULL into column 'UserId', table
My .cs code is:
int CommentID = int.Parse(ListView1.DataKeys[e.ItemIndex].Value.ToString());
ListViewItem item = ListView1.Items[e.ItemIndex];
TextBox Title = (TextBox)item.FindControl("Title");
TextBox commentContent = (TextBox)item.FindControl("commentContent");
string connectionString = ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString1"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
{
string sql = "Update Comments set Title = #Title, commentContent=#commentContent where CommentID = #CommentID";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("#Title", TextBox1.Text.Trim());
cmd.Parameters.AddWithValue("#commentContent", TextBox2.Text.Trim());
cmd.Parameters.AddWithValue("#CommentID", CommentID);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
I think the UserID column in the table is having NOT NULL constraint.Check your table schema.
It seems to me, the UserID has a not null constraint. Check in your database for that.
I think that UserId is your foreign key, you must define one foreign key
Comments contains UserId as Foreign Key, you must set UserId, because key can't be null

Checking for Primary Key assignment

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/

C# : SQL Server query issue

I create a table in SQL Server Management Studio with this code:
CREATE TABLE contact(
ID INT IDENTITY NOT NULL,
FIRSTNAME VARCHAR(100),
LASTNAME VARCHAR(100)
)
and in C# I used this code:
SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE");
SqlDataAdapter sd = new SqlDataAdapter();
sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID, #FIRSTNAME, #LASTNAME)");
sd.InsertCommand.Parameters.Add("#ID", SqlDbType.Int).Value = textBox1.Text;
sd.InsertCommand.Parameters.Add("#FIRSTNAME", SqlDbType.VarChar).Value = textBox2.Text;
sd.InsertCommand.Parameters.Add("#LASTNAME", SqlDbType.VarChar).Value = textBox3.Text;
sc.Open();
sd.InsertCommand.ExecuteNonQuery();
sc.Close();
but when I add the values to the database I get the error:
"ExecuteNonQuery: Connection property has not been initialized"
and I fixed it by adding sc to my first insertcommand, but when I run the program I got another error :
An explicit value for the identity column in table 'contact' can only
be specified when a column list is used and IDENTITY_INSERT is ON.
Do it this way:
using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE"))
{
using(SqlCommand command = new SqlCommand())
{
command.CommandText = "INSERT INTO contact (FirstName, LastName) VALUES(#FIRSTNAME , #LASTNAME");
command.CommandType = CommandType.Text;
command.Connection = sc;
command.Parameters.AddWithValue("#FIRSTNAME", textBox2.Text);
command.Parameters.AddWithValue("#LASTNAME", textBox3.Text);
sc.Open();
command.ExecuteNonQuery();
}
}
Important things to note:
1) Set your table up to have the Id column as an identity column and set autoincrement to true. This will automatically generate a numeric id when you insert
2) You are trying to insert into an identity column - you can't actually do this unless you enable identity inserts. I wouldn't bother - just use an autoincrement column and let the database control the id generation step.
You can generate your table this way:
CREATE TABLE Contact
(
Id int PRIMARY KEY IDENTITY,
FirstName varchar(100),
LastName varchar(100)
)
to get an autoincrementing primary key.
3) You don't need the SqlDataAdapter.
You need to pass the connection you intend to use to the SqlCommand
InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID , #FIRSTNAME , #LASTNAME)", sc);
You need to dispose of your Connection and command as well. The standard pattern for doing this is:
using (SqlConnection conn = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE")){
conn.Open();
using (SqlCommand command = new SqlCommand(sqlString, conn)){
//stuff...
command.ExecuteNonQuery();
}
}
There's no relation between SqlConnection and SqlDataAdapter.
In fact, you don't need SqlDataAdapter. You only need SqlConnection and SqlCommand, for which you must use the constructor overload that accepts a connection as well.
Since ID is an INT IDENTITY field, you shouldn't (and can't) insert values into it. But if you use your "generic" INSERT statement without explicitly specifying which columns to insert values into, your INSERT statement will attempt to insert data into all columns - including ID, which you cannot insert anything into.
The solution (which I recommend for use always) is to explicitly define which columns to insert values into:
INSERT INTO dbo.contact(FirstName, LastName) VALUES(#FIRSTNAME, #LASTNAME)
This also works if you need to change your table and add another column - your original statement will fail, since the table suddenly now would have four columns, but your statement would only provide three values. If you explicitly define which columns you want to provide values for, your statement is more robust and works better.
So your complete code should look like this:
using(SqlConnection sc = new SqlConnection("Data Source=.\\SQLSERVER; Initial Catalog=BOSS; Integrated Security=TRUE"))
using(SqlCommand cmdInsert = new SqlCommand("INSERT INTO dbo.Contact(FirstName, LastName) VALUES(#FIRSTNAME, #LASTNAME)", sc))
{
cmdInsert.Parameters.Add("#FIRSTNAME", SqlDbType.VarChar, 100).Value = textBox2.Text;
cmdInsert.Parameters.Add("#LASTNAME", SqlDbType.VarChar, 100).Value = textBox3.Text;
sc.Open();
cmdInsert.ExecuteNonQuery();
sc.Close();
}
You need sd.InsertCommand = new SqlCommand("INSERT INTO contact VALUES(#ID , #FIRSTNAME , #LASTNAME)", sc);
You can do either ways:
a. Set you connection object to the adapter's insertcommand connection:
sd.InsertCommand.Connection = sc;
Or
b. Pass your connection object while initializing insert command as below:
sd.InsertCommand =
new SqlCommand("INSERT INTO contact VALUES(#ID, #FIRSTNAME, #LASTNAME)", sc);

Categories