I have simple asp.net web app. That has multiple users who can login and edit Info. However, I have noticed when users are updating info at the same time.When data goes to the MS SQL DB the data is swapped.
Example
UserA was editing Item1, while UserB was editing Item2. On updating the info, it shows UserA was editing Item2.
On login User's Credentials are stored in a session
HttpContext.Current.Session.Add("Username", rs["Username"].ToString());
Code below is used to call the procedure in DB
using (SqlConnection con = new SqlConnection(dc.Con)) {
using (SqlCommand cmd = new SqlCommand("sp_EditItem", con)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ItemName", SqlDbType.VarChar).Value = txtItemInfo.Text;
cmd.Parameters.Add("#ItemID", SqlDbType.VarChar).Value = txtItemID.Text;
con.Open();
cmd.ExecuteNonQuery();
}
}
Query in the procedure
Update tb_Items
set ItemName = #ItemName
where ItemID = #ItemID
When a single user is updating the data, data is updated correctly.
What causes data to be swapped when multiple users are editing info?
Use SQL Transaction and modify code as below
using (SqlConnection con = new SqlConnection(dc.Con)) {
using (SqlCommand cmd = new SqlCommand("sp_EditItem", con)) {
using (SqlTransaction transaction = connection.BeginTransaction("SampleTransaction"))
{
try
{
cmd.Transaction = transaction;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ItemName", SqlDbType.VarChar).Value = txtItemInfo.Text;
cmd.Parameters.Add("#ItemID", SqlDbType.VarChar).Value = txtItemID.Text;
con.Open();
cmd.ExecuteNonQuery();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}
}
Related
I want MySql to insert into a table with the below query,
using (MySqlConnection con = new MySqlConnection(GetC.path))
{
con.Open();
string query = "INSERT INTO `SALES` (ID, QUANTITY, `SOLD AMOUNT`) " +
"VALUES (#id, #qty, #soldamount)";
using (MySqlCommand cmd = new MySqlCommand(query, con))
{
cmd.Parameters.AddWithValue("id",ID);
cmd.Parameters.AddWithValue("qty",quantity);
cmd.Parameters.AddWithValue("soldamount",soldAmount);
status = Convert.ToInt32(cmd.ExecuteNonQuery());
}
con.Close();
}
then update another table with below query immediately 'status' >= 1;
using (MySqlConnection con = new MySqlConnection(GetC.path))
{
con.Open();
string query = "UPDATE PRODUCTS SET QUANTITY=#qty WHERE PRODUCT=#pro";
using (MySqlCommand cmd = new MySqlCommand(query, con))
{
cmd.Parameters.AddWithValue("#qty", newQuanity);
cmd.Parameters.AddWithValue("#pro", product);
cmd.ExecuteNonQuery();
stats = Convert.ToInt32(cmd.ExecuteNonQuery());
if(stats >=1){
//alert successful
}
}
con.Close();
}
My code works fine, until there is internet breakdown, assuming the insertion was successful before internet breakdown, MySql automatically ignore the update and display and error!!
Is there a way to make MySql wait for the internet to continue the update immediately internet is back?
I am trying to update username from MVC .Net C# after connecting Postgres SQL.
I am able to establish the connection and if I run select command I am able to get the result.
But when I am trying to update record no error comes but updated count comes 0. Record available in database.
Can you please suggest what could be the reason.
using (NpgsqlConnection con = new NpgsqlConnection(connectionString))
{
string query = string.Format("UPDATE um_user SET um_user_name='{0}' WHERE um_user_name='{1}'", updatedUser, userNameToBeUpdated);
con.Open();
NpgsqlCommand comn = new NpgsqlCommand(query, con);
comn.Connection = con;
updatedRows = comn.ExecuteNonQuery();
comn.Dispose();
con.Close();
}
I have added using parameter as well with the following code but still getting 0 updtaed rows.
using (NpgsqlConnection connection = new NpgsqlConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
NpgsqlCommand cmd = new NpgsqlCommand();
cmd.Connection = connection;
cmd.CommandText = "update um_user set um_user_name=#newName where um_user_name=#oldName";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new NpgsqlParameter("#newName", updatedUser));
cmd.Parameters.Add(new NpgsqlParameter("#oldName", userNameToBeUpdated));
updatedRows = cmd.ExecuteNonQuery();
cmd.Dispose();
connection.Close();
}
When creating User, I need to give it a system Role, so I was wondering what is the best way to do that.
I have working solution, but I'm unsure if it's the best way.
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand(#"INSERT INTO Users (Name, Email, Username, Password, Active) VALUES (#Name, #Email, #Username, #Password, #Active); SELECT SCOPE_IDENTITY();", con))
{
try
{
cmd.Parameters.AddWithValue("#Name", user._Name);
cmd.Parameters.AddWithValue("#Email", user._Email);
cmd.Parameters.AddWithValue("#Username", user._Email);
cmd.Parameters.AddWithValue("#Password", user.Password);
cmd.Parameters.AddWithValue("#Active", 1);
user_id = Convert.ToInt32(cmd.ExecuteScalar());
//cmd.ExecuteNonQuery();
}
catch (SqlException)
{
//Handle Exception
}
}
}
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlCommand cmd = new SqlCommand("INSERT INTO User_Role (User_Role_User_Id, User_Role_Role_Id) VALUES (#User_ID, #Role_ID)", con))
{
try
{
cmd.Parameters.AddWithValue("#User_ID", user_id);
cmd.Parameters.AddWithValue("#Role_ID", user.Role_ID);
cmd.ExecuteNonQuery();
}
catch (SqlException)
{
//Handle Exception
}
}
}
Now my problem is, if adding the role goes wrong for whatever reason, I'll have a user created without a role.
So I was wondering if it's possible to join the two SqlCommand, considering that I need the Scope_Identity for the insert into User_Role. Or do a rollback on the last exception catch for both Insert's?
Either make a stored procedure that does the work as an atomic unit, or if you are unable to do that, you can wrap the entire code block in a transaction if yo keep using the same connection, like this:
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
var transaction = con.BeginTransaction();
try
{
//Run first command
//Run second command
//If we have succeeded, commit the transaction
transaction.Commit();
}
catch()
{
//Something went wrong, roll back
transaction.Rollback();
}
}
I'm trying to implement an sql transaction, however, i've run into a bit of bother. I have a simple database with has three tables. Users, Post and Comments. I wish to implement a delete button that will delete a user from the Users table. The initial problem I had was that I needed to remove the users FK from both the post and comment table, then remove the user from the User table. I looked online and somebody had suggested using transaction for multiple server calls. Here is my code:
public void DeleteUser(int UserId)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlTransaction sqlTran = con.BeginTransaction();
try
{
using (SqlCommand command = new SqlCommand("DELETE FROM Comment WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
using (SqlCommand command = new SqlCommand("DELETE FROM Post WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
using (SqlCommand command = new SqlCommand("DELETE FROM Users WHERE UserId = " + #UserId, con))
{
SqlParameter userid = new SqlParameter("#UserId", SqlDbType.Int);
userid.Value = UserId;
command.ExecuteNonQuery();
}
sqlTran.Commit();
}
catch
{
sqlTran.Rollback();
}
}
}
The problem I have is that when the DeleteUser method is run, the program gets as far as the command.ExecutyNonQuery in the first using block, then jumps to the catch. Thus rolling back the changes. There isn't any error codes displayed, so i'm not sure what is going wrong.
Any help in this matter would be greatly appreciated.
You're missing command.Transaction = sqlTran;.
DO NOT USE try {} catch {}. Use at least try {} catch (Exception ex) {} -> this will give you enough information to solve the problem on your own.
This is a really, really stupid question but I am so accustomed to using linq / other methods for connecting and querying a database that I never stopped to learn how to do it from the ground up.
Question: How do I establish a manual connection to a database and pass it a string param in C#? (yes, I know.. pure ignorance).
Thanks
using (SqlConnection conn = new SqlConnection(databaseConnectionString))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "StoredProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ID", fileID);
conn.Open();
using (SqlDataReader rdr =
cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (rdr.Read())
{
// process row from resultset;
}
}
}
}
One uses the SqlCommand class to execute commands (either stored procedures or sql) on SQL Server using ado.net. Tutorials abound.
Here's an example from http://www.csharp-station.com/Tutorials/AdoDotNet/Lesson07.aspx
public void RunStoredProcParams()
{
SqlConnection conn = null;
SqlDataReader rdr = null;
// typically obtained from user
// input, but we take a short cut
string custId = "FURIB";
Console.WriteLine("\nCustomer Order History:\n");
try
{
// create and open a connection object
conn = new
SqlConnection("Server=(local);DataBase=Northwind;Integrated Security=SSPI");
conn.Open();
// 1. create a command object identifying
// the stored procedure
SqlCommand cmd = new SqlCommand(
"CustOrderHist", conn);
// 2. set the command object so it knows
// to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which
// will be passed to the stored procedure
cmd.Parameters.Add(
new SqlParameter("#CustomerID", custId));
// execute the command
rdr = cmd.ExecuteReader();
// iterate through results, printing each to console
while (rdr.Read())
{
Console.WriteLine(
"Product: {0,-35} Total: {1,2}",
rdr["ProductName"],
rdr["Total"]);
}
}
finally
{
if (conn != null)
{
conn.Close();
}
if (rdr != null)
{
rdr.Close();
}
}
}
3 things no one else has shown you yet:
"Stacking" using statements
Setting an explicit parameter type rather than letting .Net try to pick one for you
"var" keyword
.
string sql = "MyProcedureName";
using (var cn = new SqlConnection(databaseConnectionString))
using (var cmd = new SqlCommand(sql, cn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ParameterName", SqlDbType.VarChar, 50)
.Value = "MyParameterValue";
conn.Open();
using (SqlDataReader rdr =
cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
if (rdr.Read())
{
// process row from resultset;
}
}
}