Adding data to database in parts (asp.net) - c#

I have a couple of pages for booking and each page saves data. For example page one adds the destination to the database, page two is selecting amount of passengers.
I have a table to store all this:
CREATE TABLE [dbo].[Transactions] (
[cardNumber ] NCHAR (10) NULL,
[Cost] NCHAR (10) NULL,
[Passengers] NCHAR (10) NULL,
[Destination] NCHAR (10) NULL
);
On the destination page I am using the following code to input the destination to the database:
protected void Button2_Click1(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString);
conn.Open();
string insert = "insert into Transactions (Destination) values (#Destination)";
SqlCommand com = new SqlCommand(insert, conn);
com.Parameters.AddWithValue("#Destination", DropDownList1.SelectedItem);
com.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
Response.Write("Error: " + ex.ToString());
}
Response.Redirect("Booking.aspx");
}
On the next page I have relatively the same code to enter the amount of passengers:
protected void Button2_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString);
conn.Open();
string insert = "insert into Transactions (Passengers) values (#Passengers)";
SqlCommand com = new SqlCommand(insert, conn);
com.Parameters.AddWithValue("#Passengers", DropDownList1.SelectedItem);
com.ExecuteNonQuery();
conn.Close();
}
catch(Exception ex)
{
Response.Write("Error: " + ex.ToString());
}
Response.Redirect("Payment.aspx");
}
But after doing this no data gets entered into the database. If anyone knows of anyway that I can enter data into the database one piece at a time please let me know.
If it can’t be done this way and there is a much better way of doing this again please let me know.
Thank you all for your time.

You should have a dedicated primary key column on your table, I recommend an autoincrementing integer.
CREATE TABLE [dbo].[Transactions]
(
[ID] INT NOT NULL PRIMARY KEY IDENTITY(1,1),
[CardNumber] NCHAR (10) NULL,
[Cost] NCHAR (10) NULL,
[Passengers] NCHAR (10) NULL,
[Destination] NCHAR (10) NULL
);
Then, use stored procedures, not ad-hoc SQL.
CREATE PROCEDURE TransactionSave
(
#ID int = null,
#CardNumber nchar(10) = null,
#Cost nchar(10) = null,
#Passengers nchar(10) = null,
#Destination nchar(10) = null
)
AS
BEGIN
DECLARE #ExistingID int
SELECT #ExistingID = ID FROM Transaction WHERE ID = #ID
IF #ExistingID is null
BEGIN
--Insert
INSERT INTO Transaction (CardNumber, Cost, Passengers, Destination)
VALUES (#CardNumber, #Cost, #Passengers, #Destination)
SELECT CAST(SCOPE_IDENTITY() AS INT) AS 'TransactionID'
END
ELSE
BEGIN
--Update
UPDATE Transaction
SET
CardNumber = ISNULL(#CardNumber, CardNumber),
Cost = ISNULL(#Cost, Cost),
Passengers = ISNULL(#Passengers, Passengers),
Destination = ISNULL(#Destination, Destination),
WHERE ID = #ExistingID
SELECT #ExistingID AS 'TransactionID'
END
END
Then, in your code behind, you need to retain the ID value of the Transaction you are working on, to be sure you're updating the proper row:
protected void Button2_Click(object sender, EventArgs e)
{
int transactionID = hfID.Value;
try
{
using(SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseConnectionString"].ConnectionString))
{
SqlCommand cmd = new SqlCommand("TransactionSave", conn);
cmd.Parameters.AddWithValue("#ID", transactionID);
cmd.Parameters.AddWithValue("#Passengers", DropDownList1.SelectedValue);
transactionID = cmd.ExecuteScalar();
hfID.Value = transactionID;
}
}
catch(Exception ex)
{
Response.Write("Error: " + ex.ToString());
}
}

Related

What is a trick procedure does?

I need to update the value in MySQL DB, so in order to do it I use procedure.
There is my DB
CREATE TABLE `sessions` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`manager_name` VARCHAR(1024) NOT NULL COLLATE 'utf8_general_ci',
`created_date` DATETIME NOT NULL,
`num_works` INT(10) NOT NULL DEFAULT '0',
`num_jobs` INT(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=306
;
There is my procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `session_update_works_num`(
IN `id` INT,
IN `num_works` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'use this procedure to update works num'
BEGIN
UPDATE `gmdb`.`sessions` SET `num_works`=num_works WHERE `id`=id;
END
There is how I use it in my C# code
protected override void Execution()
{
using (MySqlConnection conn = DBConnection.Instance.Connection)
{
try
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText = PROCEDURE_UPDATE_WORKS_NUM;
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue($"#{Constants.SESSION_TABLE_ID}", SessionSingleton.Instance.SessionId);
cmd.Parameters.AddWithValue($"#{Constants.SESSION_TABLE_NUM_WORKS}", m_worksNum);
cmd.ExecuteNonQuery();
SetTaskStatus(State.COMPLETED);
};
}
catch (Exception e)
{
ErrorMsg += $"ERROR: while execute procedure : {PROCEDURE_UPDATE_WORKS_NUM}, error: {e.ToString()}";
SetTaskStatus(State.FAILED);
}
}
}
The problem is that if for example, I have a few lines in my DB
After the procedure will be executed num_works field will be changed for all the lines.
But if I change the code and use a query instead of a procedure all works fine:
protected override void Execution()
{
using (MySqlConnection conn = TV_DP_DBConnection.Instance.Connection)
{
try
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand())
{
string query = $"UPDATE `gmdb`.`sessions` SET `num_works`={m_worksNum} WHERE `id`={SessionSingleton.Instance.SessionId};";
cmd.CommandText = query;
cmd.Connection = conn;
cmd.ExecuteNonQuery();
SetTaskStatus(State.COMPLETED);
};
}
catch (Exception e)
{
ErrorMsg += $"ERROR: while execute procedure : {PROCEDURE_UPDATE_WORKS_NUM}, error: {e.ToString()}";
SetTaskStatus(State.FAILED);
}
}
}
What is the problem here? How is it possible that I pass to procedure exact id WHERE 'id'=id but all the lines have an effect?
I think CrowCoder is right, variable names in stored procedure are the same as column names. Change variable names both in SP and code, and try again.

What is the best way to account for duplicate entries in datagridview with C# and SQL?

This windows application displays student information in a datagridview. When the table is double clicked, another form appears for editing the data.
When duplicates for StudentName exist, when doubleclicking the latest entry, only the earliest entry for StudentName appears. Also, when editing any data for a particular student, all duplicated entries get edited as well!
I was trying modify the code so that it would load the data based on StudentId instead of StudentName. An alternative idea was to implement a change in the code so that the user cannot enter duplicate entries.
What would be the best approach to solving this?
ViewStudentForm.cs
private void StudentDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if(StudentDataGridView.Rows.Count > 0)
{
string studentName = StudentDataGridView.SelectedRows[0].Cells[1].Value.ToString();
StudentForm studentForm = new StudentForm();
studentForm.StudentName = studentName;
studentForm.IsUpdate = true;
studentForm.ShowDialog();
LoadDataIntoDataGridView();
}
}
private void LoadDataIntoDataGridView()
{
using (SqlConnection con = new SqlConnection(AppConnection.GetConnectionString()))
{
using (SqlCommand cmd = new SqlCommand("usp_Students_LoadDataIntoDataGridView", con))
{
cmd.CommandType = CommandType.StoredProcedure;
if (con.State != ConnectionState.Open)
con.Open();
DataTable dtStudents = new DataTable();
SqlDataReader sdr = cmd.ExecuteReader();
dtStudents.Load(sdr);
StudentDataGridView.DataSource = dtStudents;
}
}
}
StudentForm.cs
public string StudentName { get; set; }
public bool IsUpdate { get; set; }
private void SaveButton_Click(object sender, EventArgs e)
{
//Do Insert Process
using (SqlConnection con = new SqlConnection(AppConnection.GetConnectionString()))
{
using (SqlCommand cmd = new SqlCommand("usp_Students_InsertNewStudent", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#StudentName", StudentNameTextBox.Text.Trim());
cmd.Parameters.AddWithValue("#Age", AgeTextBox.Text.Trim());
cmd.Parameters.AddWithValue("#Gender", GenderTextBox.Text.Trim());
cmd.Parameters.AddWithValue("#Description", DescriptionTextBox.Text.Trim());
if (con.State != ConnectionState.Open)
con.Open();
cmd.ExecuteNonQuery();
MessageBox.Show("Student is successfully added in the database.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
ResetFormControl();
}
}
}
Stored Procedure for usp_Students_InsertNewStudent
ALTER PROCEDURE [dbo].[usp_Students_InsertNewStudent]
(
#StudentName NVARCHAR(200)
,#Age NVARCHAR(50)
,#Gender NVARCHAR(50)
,#Description NVARCHAR(MAX)
,#Image IMAGE
,#CreatedBy NVARCHAR(50)
)
AS
BEGIN
INSERT INTO [dbo].[Students]
([StudentName]
,[Age]
,[Gender]
,[Description]
,[Image]
,[CreatedBy]
,[CreatedDate])
VALUES
(
#StudentName
,#Age
,#Gender
,#Description
,#Image
,#CreatedBy
,GETDATE()
)
END
A few things:
You need to identify something in the real world that constitutes uniqueness for your student. Even a combination of student name, age and gender would not be unique. This is why schools give out a student id that uniquely identifies a student. Once you know what that is, add it to your table and put a unique constraint on it.
Once this is set, then you need validation on the front end to prevent an error from occurring in your database if a user sends a duplicate in. This looks to be a desktop app with no tiers between the front end and back end so should be speedy to check the DB and give user feedback immediately.
If for whatever reason, you can't do #2, then in your stored procedure, you can before you insert, check for existence because if you don't check, your constraint will kick out an error and if unhandled will crash your app.
ALTER PROCEDURE [dbo].[usp_Students_InsertNewStudent]
(
#StudentName NVARCHAR(200)
,#Age NVARCHAR(50)
,#Gender NVARCHAR(50)
,#Description NVARCHAR(MAX)
,#Image IMAGE
,#CreatedBy NVARCHAR(50)
)
AS
BEGIN
if not exists (select 'x' from dbo.Students where uniquekey=#passedinuniquekey)
BEGIN
INSERT INTO [dbo].[Students]
([StudentName]
,[Age]
,[Gender]
,[Description]
,[Image]
,[CreatedBy]
,[CreatedDate])
VALUES
(
#StudentName
,#Age
,#Gender
,#Description
,#Image
,#CreatedBy
,GETDATE()
)
END
END
Lastly, I would do this in the actual code that calls this stored procedure
int rowsAffected = cmd.ExecuteNonQuery();
if (rowsAffected>0)
{
MessageBox.Show("Student is successfully added in the database.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
ResetFormControl();
}
else
// Failed message here
I changed some code for the doubleclick handler within the ViewStudentForm.cs
In this context I think it better to perform the load operation based on Id instead of student name.
private void StudentDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if(StudentDataGridView.Rows.Count > 0)
{
int StudentId = Convert.ToInt32(StudentDataGridView.SelectedRows[0].Cells[0].Value);
StudentForm studentForm = new StudentForm();
studentForm.StudentId = StudentId;
studentForm.IsUpdate = true;
studentForm.ShowDialog();
LoadDataIntoDataGridView();
}
}

I am using Visual Studio and I have a SQL Server table, but when I insert data, I get an error

I am trying to insert data into a SQL Server table, but it is not allowing me to do so and throws an error. I think the error is from the role I don't know how to fix it; please I need your help - thank you.
This is the member table that I am using:
CREATE TABLE [dbo].[Member]
(
[Member_Username] NVARCHAR (50) NOT NULL,
[Password] NVARCHAR (25) NOT NULL,
[Role] NVARCHAR (10) NULL,
[FirstName] NVARCHAR (50) NOT NULL,
[LastName] NVARCHAR (50) NOT NULL,
[Gender] NVARCHAR (8) NOT NULL,
[Email] NVARCHAR (50) NULL,
[DateOfBirth] DATE NOT NULL,
PRIMARY KEY CLUSTERED ([Member_Username] ASC)
);
And this is the error I get when inserting the values into the table:
System.Data.SqlClient.SqlException:
The parameterized query '(#memberU nvarchar(1), #pwd nvarchar(1), #role nvarchar(4000), #fna' expects the parameter '#role', which was not supplied.
This is the member class that I have for inserting the user in the database table:
public void AddMember()
{
// Open database connection
SqlConnection conn = new SqlConnection();
conn.ConnectionString = Config.GetConnectionStr();
conn.Open();
// Prepare SQL command with parameters
string sql = "INSERT INTO Member VALUES (#memberU, #pwd, #role, #fname, #lname, #gender, #email, #dob)";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("memberU", this.Member_Username);
cmd.Parameters.AddWithValue("pwd", this.Password);
cmd.Parameters.AddWithValue("role", this.Role);
cmd.Parameters.AddWithValue("fname", this.FirstName);
cmd.Parameters.AddWithValue("lname", this.LastName);
cmd.Parameters.AddWithValue("email", this.Email);
// handling null values for gender and date of birth column
if (this.Gender != null)
{
cmd.Parameters.AddWithValue("gender", this.Gender);
}
else
{
cmd.Parameters.AddWithValue("gender", DBNull.Value);
}
if (this.DateofBirth != null)
{
cmd.Parameters.AddWithValue("dob", this.DateofBirth);
}
else
{
cmd.Parameters.AddWithValue("dob", DBNull.Value);
}
// Execute command
cmd.ExecuteNonQuery();
}
And this is the sign up button:
protected void btnSignUp_Click(object sender, EventArgs e)
{
if (Page.IsValid)// assuming you have done validations using validation controls
{// c create a new object of type member and set all it's properties to values from controls
Members user = new Members();
//reading required values
user.FirstName = txtFirstName.Text;
user.LastName = txtLastName.Text;
user.Member_Username = txtUserName.Text;
user.Password = txtPassword.Text;
user.Email = txtEmail.Text;
user.Gender = rdoGender.SelectedValue;
//reading values that allow null in the database (date of birth)
if (string.IsNullOrEmpty(txtDOB.Text))
{
user.DateofBirth = null;
}
else
{
user.DateofBirth = DateTime.Parse(txtDOB.Text);
}
//call the addMember method
user.AddMember();
//redirect the user to homePage
Response.Redirect("Login.aspx");
}
}
can you try when you add parameters like ( cmd.parameters.addwithvalue("#role",value).

Check if table creation was successful

I have a Winforms app that has to migrate data from SQL to MySQL. Part of the functionality requires preparing the target database by adding the required tables (and dropping existing tables if necessary).
I'm looking for the most efficient way to determine if the table was created successfully. This question's answer suggested that executing the query would return an integer value greater than 0 if it was successful. Ideally, I'd like to execute the command and use a return value rather than running another query. Is this possible?
My current code:
MySqlConnection myConnection = new MySqlConnection(ConnectionString);
string sql = #" DROP TABLE IF EXISTS `sf_root_items`;
CREATE TABLE `sf_root_items` (
`ID` varchar(255) NOT NULL,
`LoweredName` varchar(255) DEFAULT NULL,
`MenuName` varchar(255) DEFAULT NULL,
`Title` varchar(255) DEFAULT NULL,
`Description` varchar(255) DEFAULT NULL,
`PageType` varchar(255) DEFAULT NULL,
`ExternalUrl` varchar(255) DEFAULT NULL,
PRIMARY KEY(`ID`)
)";
MySqlCommand cmd;
try
{
if (myConnection.State != ConnectionState.Open)
{
myConnection.Close();
myConnection.Open();
}
cmd = myConnection.CreateCommand();
cmd.CommandText = sql;
int output = cmd.ExecuteNonQuery();
// a value greater than 0 means execution was successful
if (output > 0)
{
DBPrepDone = "Table created";
}
else
{
DBPrepDone = "There was an error";
}
myConnection.Close();
}
catch (Exception ex)
{
DBPrepDone = ex.ToString();
}
Here is a description of ExecuteNonQuery return values from Microsoft site
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executenonquery%28v=vs.110%29.aspx
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data. 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. If a rollback occurs, the return
value is also -1.
To make your query work you should add check of existing your table, for example
string sql = #" DROP TABLE IF EXISTS `sf_root_items`;
CREATE TABLE `sf_root_items` (
`ID` varchar(255) NOT NULL,
`LoweredName` varchar(255) DEFAULT NULL,
`MenuName` varchar(255) DEFAULT NULL,
`Title` varchar(255) DEFAULT NULL,
`Description` text,
`PageType` varchar(255) DEFAULT NULL,
`ExternalUrl` varchar(255) DEFAULT NULL,
PRIMARY KEY(`ID`)
)";
string sql_check = #" SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_NAME = 'sf_root_items')
AND (TABLE_SCHEMA = '" + WP_db.Text +"')";
MySqlCommand cmd;
try
{
if (myConnection.State != ConnectionState.Open)
{
myConnection.Close();
myConnection.Open();
}
cmd = myConnection.CreateCommand();
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
//call check if table was created
cmd = myConnection.CreateCommand();
cmd.CommandText = sql_check;
var test = cmd.ExecuteScalar();
int output;
int.TryParse(test.ToString(), out output);
// a value greater than 0 means execution was successful
if (output > 0)
{
DBPrepDone = "Table 'sf_root_items' has been created";
}
else
{
DBPrepDone = "There was an error";
}
myConnection.Close();
}
catch (Exception ex)
{
DBPrepDone = ex.ToString();
}

Violation of Primary Key constraint windowsForms

I would like to insert a record into my RDV Table.
This is the query creation of my table
CREATE TABLE [dbo].[RDV] (
[idRdv] INT NOT NULL,
[objet] NVARCHAR (50) NULL,
[objectif] NVARCHAR (50) NULL,
[DateRdv] DATETIME NULL,
[commentaire] NVARCHAR (50) NULL,
[archive] NVARCHAR (50) NULL,
[idClient] INT NULL,
[idUser] INT NULL,
[idResultat] INT NULL,
CONSTRAINT [PK_RDV] PRIMARY KEY CLUSTERED ([idRdv] ASC),
FOREIGN KEY ([idClient]) REFERENCES [dbo].[Client] ([idClient]),
FOREIGN KEY ([idUser]) REFERENCES [dbo].[User] ([idUser]),
FOREIGN KEY ([idResultat]) REFERENCES [dbo].[Resultat] ([idResultat]);
and this is my code of insert
public RDV()
{
InitializeComponent();
textBox3.Visible = false;
label7.Visible = false;
}
private void btnAdd_Click(object sender, EventArgs e)
{
Random rdm = new Random();
int num = rdm.Next(5, 2000);
textBox3.Text = num.ToString();
string cmdStr = "Insert into RDV (idRdv,idUser,idClient,objet,objectif,DateRdv,commentaire) select #idRdv,#idUser,#idClient,#objet,#objectif,#DateRdv,#commentaire from RDV, Client, [User] where RDV.idClient = Client.idClient and RDV.idUser = [User].idUser ";
SqlConnection con = new SqlConnection("Data Source=ADMIN-PC\\SQLEXPRESS;Initial Catalog=timar;Integrated Security=True");
SqlCommand cmd = new SqlCommand(cmdStr, con);
cmd.Parameters.AddWithValue("#idRdv", textBox3.Text);
cmd.Parameters.AddWithValue("#idUser", (comboBox1.SelectedValue));
cmd.Parameters.AddWithValue("#idClient", (comboBox2.SelectedValue));
cmd.Parameters.AddWithValue("#objet", textBox1.Text);
cmd.Parameters.AddWithValue("#objectif", textBox2.Text);
cmd.Parameters.AddWithValue("#DateRdv", dateTimePicker1.Value.ToString());
cmd.Parameters.AddWithValue("#commentaire", textBox4.Text);
con.Open();
int LA = cmd.ExecuteNonQuery();
Console.WriteLine("Ligne ajoutée: {0}", LA);
And,the field idRdv , i want to add it but should be hidden and Random like in the code above.
When , I run my project , it shows me an error Violation of PRIMARY KEY " PK_RDV ". Can not insert duplicate key in object ' dbo.RDV ". Value of Duplicate Key:1505 (this the value of idRdv)
Pleaaaaseee, help me. How should I correct it.
Thanks in advance
You are using the ID with Random. As your table ID column is containing Primary Key Constraint it may get this error.
Either you check that the random number generated is not exist in the table before insert. Or use a method to get Max(ID)+1 and set this as new ID

Categories