Reputation: 13824
I got 3 tables: projects, managers and project_manager
managers
projects
project_manager
Assume that a manager is currently logged-in (so we know what manager_id is) and he want to create a new Project, by entering a name into txtName textbox and hit "create" button. I tried to write:
(1) a query to insert a new project (name) into projects table and
(2) a single query that insert project_id & manager_id into project_manager table
but got syntax error at the third query string and this is not a good way since inserting into projects table (query 1) may be succeeded but inserting into other table (query 2) may be failed, I dont know much "advanced stuff" of SQL, definitely need help:
string CS = ConfigurationManager.ConnectionStrings["CTECS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
string q1 = "SELECT COUNT(*) FROM [projects] WHERE project_name = @Name";
SqlCommand cmd = new SqlCommand(q1, con);
cmd.Parameters.AddWithValue("@Name", txtName.Text);
con.Open();
int i = (int)cmd.ExecuteScalar();
if (i < 1)
{
string Command = "INSERT INTO [dbo].[projects] (project_name) VALUES (@Name)";
cmd = new SqlCommand(Command, con);
cmd.Parameters.AddWithValue("@Name", txtName.Text);
cmd.ExecuteNonQuery();
Command = "INSERT INTO [project_manager] (project_id, manager_id) VALUES (SELECT project_id FROM [projects] WHERE project_name = @Name, @ID)";
cmd = new SqlCommand(Command, con);
// Provide the value for the parameter
cmd.Parameters.AddWithValue("@Name", txtName.Text);
cmd.Parameters.AddWithValue("@ID", currentUser.userID.ToString());
cmd.ExecuteNonQuery();
}
else
{
Panel1.Visible = true;
lblMessage.CssClass = "alert alert-error";
lblMessage.Text = "This project's name has been already used.";
return;
}
}
Upvotes: 0
Views: 6551
Reputation: 5798
First of all, you transfer your whole logic in stored procedure which is safe and easily maintainable. Also there is only one hit to sqlserver rather than 3 in your case.
Also good as use @@identity or SCOPE_IDENTITY() to get id of inserted project-id.
So make one sp and code like @Hamlet-Hakobyan suggested. Try to make world simple from complex, not complex from simple.
Your code is good to understand as basic things, but not in professional scenario.
Upvotes: 1
Reputation: 33381
Do you use the server in single_user mode? I don't think so. At first you must do it in the transaction. The best way to do it - SP. Checking the existence of project doesn't guarantee that it not exists when you insert it.
CREATE PROC usp_InsertProject(@project_name varchar(255), @manager_id int)
AS
SET NOCOUNT ON
DECLARE @project_id int
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[projects] (project_name) VALUES (@project_name)
SELECT @project_id = SCOPE_IDENTITY()
INSERT INTO [project_manager] (project_id, manager_id)
VALUES(@project_id, @manager_id)
COMMIT TRAN
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber
,ERROR_MESSAGE() AS ErrorMessage
ROLLBACK TRAN
END CATCH
GO
then
string CS = ConfigurationManager.ConnectionStrings["CTECS"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
SqlCommand cmd = new SqlCommand("usp_InsertProject", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@project_name", txtName.Text); // you must validate text value before passing
cmd.Parameters.AddWithValue("@manager_id", currentUser.userID);
con.Open();
using(SqlDataReader reader = cmd.ExecuteReader())
{
if(reader.Read())
{
// the error occured in SP
// reader[0] is error number
// record[1] is error message
}
}
}
Upvotes: 2
Reputation: 32681
Your logic is not correct here in the first place
SELECT project_id FROM [projects] WHERE project_name = @Name
may return multiple results. You may have checks in place that ensure that there can be exactly one project with one name, but system doesn't knows that and you will end up inserting multiple records into the table
A work around can be that you change it to (just to make it work)
INSERT INTO [project_manager] (project_id, manager_id) SELECT project_id, @ID FROM [projects] WHERE project_name = @Name
But, not recommended.
You need to save the id that you are generating for the project name and pass them to your query here.
INSERT INTO [project_manager] (project_id, manager_id) VALUES (@ProjectID, @ID)
Upvotes: 1
Reputation: 5189
I think the third sql statement should be:
INSERT INTO [project_manager] (project_id, manager_id) SELECT project_id, @ID FROM [projects] WHERE project_name = @Name
Upvotes: 4