0

Currently I have an insert query to my table and I don't have any idea how I can validate it, if the data is already exists in the table.

So for now I just used try-catch to handle the duplicate entry. I just wondering if I could return some text If value goes to catch then display it to my view as alert or something.

Here is my query from controller:

 public ActionResult AddUser(int id, string name, string age)
 {
        string constr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;

        using (MySqlConnection con = new MySqlConnection(constr))
        {
            string sqlQuery = "INSERT INTO myTable (id, name, age) VALUES (@id, @name, @age)";
            MySqlCommand cmd = new MySqlCommand(sqlQuery, con);
            cmd.Parameters.AddWithValue("@id", id);
            cmd.Parameters.AddWithValue("@name", name);
            cmd.Parameters.AddWithValue("@age", age);

            con.Open();

            try {
                cmd.ExecuteNonQuery();
                con.Close();
                return RedirectToAction("Index");
            }
            catch (Exception )
            {
                con.Close();
                return this.Json("This Data already exist on table");
            }
        }
    }

And this is my script to read my controller query:

 function add(id, name, age) {

        var result = confirm("Are you want to add " + name + " to list?");
        if (result == true) {

            $.ajax({
                url: '/Home/AddUser',
                type: 'POST',
                data: {
                    'id': id,
                    'name': name,
                    'age': age,
                },
                success: function (data) {                                                    
                    alert('Data has been successfully added');
                },
                error: function (jqXhr, textStatus, errorThrown) {
                    alert(errorThrown);
                }
            });
        }
    }

So far I can successfully insert it to my table but if there is already exist and it's a duplicate it will do nothing so the user will not have a prompt if they already added it or already exist or not.

Any suggestions or comments. TIA.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Syntax Rommel
  • 932
  • 2
  • 16
  • 40

2 Answers2

0

Consider creating a constraint in your database table (unique constraint on that column(s)). That will prevent any duplicate records to be saved even if it passes your C# code which is talking to the database.

Add a check to see whether the record exist, just before executing the INSERT statement. You can write a SQL statement which checks before the insertion step. May be a stored procedure which has this SQL scripts which does this and you may call the stored procedure from your c# method.

There is no point in returning a redirect response if you are calling this from Ajax code. Consider returning a JSON structure which can tell the client side code whether the record was successfully inserted or duplicate found or code crashed.

Here is a quick and simple example, where I am calling the UserExist method, which checks whether there is a record with the specified name. If it returns false, I continue to execute my code where I will try to insert. If you are using a stored procedure, you can add the record exist check inside that as well.

[HttpPost]
public ActionResult AddUser(int id, string name, string age)
{
    try 
    {
       // your existing code to insert record to db
       // Check record exist
       if(UserExist(name))
       {
          return Json(new { status="failed", message = "Name exist"});
       }
       // name does not exist. Try to call the Insert code now.

       return Json(new { status="success", message = "Successfully saved"});
    }
    catch (SqlException exs)
    {
       // Check exs to see whether this was caused by unique constraint violation
       return Json(new { status="error", message = "User exist"});
    }
    catch (Exception ex)
    {
       // to do : log the exception
       return Json(new { status="error", message = "Error in saving"});
    }
}
private bool UserExist(string name)
{
   // to do: check record exist in db 
   // You may use ExecuteScalar method if you use raw ADO.NET
   // to do : return boolean value.
}

and in your success handler, check the status property of the response json and show the user the appropriate message

success:function(data)
{
  if(data.status==="success")
  {
      alert("Saved successfully");
  }
  else if(data.status==="failed")
  {
      alert(data.message);
  }
}

You can set the status property of your JSON object to failed when you are trying to insert duplicate record.

You can use specific exceptions for your exception handling part which can catch the exception when the unique key constraint is violated in the database level. Send a message to user in that catch block as well.

Shyju
  • 214,206
  • 104
  • 411
  • 497
0

The first step you can do is creating a stored procedure which has output parameters to show insertion status, which must be different when duplicate data is found:

DELIMITER //
CREATE PROCEDURE AddUser(in @id int, @name varchar(50), @age int, out @status varchar(20))
AS
BEGIN
    -- check if duplicate exists
    IF (SELECT EXISTS (SELECT 1 FROM myTable WHERE name = @name))
        BEGIN
           -- duplicate exist, no insertion to table
           SET @status = 'duplicate';
        END
    ELSE
        BEGIN
           INSERT INTO myTable (id, name, age) VALUES (@id, @name, @age)
           SET @status = 'success';
        END
    END
END
//
DELIMITER ;

Then, use the stored procedure name inside MySqlCommand and use its output parameter to return the status string:

[HttpPost]
public ActionResult AddUser(int id, string name, string age)
{
    string constr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
    using (MySqlConnection con = new MySqlConnection(constr))
    {
        string sqlQuery = "AddUser";
        MySqlCommand cmd = new MySqlCommand(sqlQuery, con);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("@id", id);
        cmd.Parameters.AddWithValue("@name", name);
        cmd.Parameters.AddWithValue("@age", age);
        cmd.Parameters.Add("@status", MySqlDbType.VarChar).Direction = ParameterDirection.Output;
        con.Open();
        try 
        {
            cmd.ExecuteNonQuery();
            con.Close();
            return Json(new { status = (string)cmd.Parameters["@status"].Value });
        }
        catch (MySqlException ex)
        {
            con.Close();
            return Json(new { status = "error", message = ex.Message });
        }
        catch (Exception e)
        {
            con.Close();
            return Json(new { status = "error", message = e.Message });
        }

    }
}

Then you can output messages depending on current status in AJAX callback:

$.ajax({
    url: '/Home/AddUser',
    type: 'POST',
    data: {
       'id': id,
       'name': name,
       'age': age,
    },
    success: function (data) {
        if (data.status === "success")
        {
            alert("Data has been successfully added");
        }
        else if (data.status === "duplicate")
        {
            alert("This Data already exist on table");
        }
        else if (data.status === "error")
        {
            alert(data.message);
        }
    }
    error: function (xhr, status, err) {
        // error handling
    }
}

If you don't want to check with SELECT query like above, consider altering the table by applying UNIQUE constraint and check against error code 1062 in MySqlException:

ALTER TABLE myTable ADD CONSTRAINT UNIQUE (name);
Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61