Let me explain my situation in full.
I have a JavaScript object like
[{"QuestionId":"1","AnswerId":"21","AnswerText":"34"},
{"QuestionId":"2","AnswerId":"22","AnswerText":"23"},...]
which I need to use to either insert or update rows of a T-SQL table generated by
CREATE TABLE Answers (
id INT IDENTITY (1,1),
question_id INT NOT NULL,
partner_id UNIQUEIDENTIFIER NOT NULL,
val INT,
PRIMARY KEY (id),
FOREIGN KEY (question_id) REFERENCES Questions(id),
FOREIGN KEY (partner_id) REFERENCES Partners(id)
);
The AJAX call is
var QAs = new Array();
$('.completeness.for-answer').each(function () {
QAs.push({
QuestionId : $(this).attr('data-qstnid'),
AnswerId : $(this).attr('data-answid'),
AnswerText : $(this).val(),
});
});
console.log(JSON.stringify(QAs));//TEST
$.ajax({
method: 'POST',
url: '/Answers/SubmitAnswers',
data : QAs,
success: function (retobj) {
console.log(retobj);
},
error: function () {
console.log("Error ...");
}
});
Each item in the list of updates, when it is transmitted to the database in the form of executing a stored procedure
CREATE PROCEDURE AddOrUpdateAnswer
@AnswerId INT,
@AnswerVal INT,
@QuestionId INT,
@PartnerId UNIQUEIDENTIFIER
AS
BEGIN
SET NOCOUNT ON
IF EXISTS ( SELECT 1 FROM Answers WHERE id=@AnswerId )
UPDATE Answers SET val=@AnswerVal WHERE id=@AnswerId
ELSE
INSERT INTO Answers (question_id, partner_id, val) VALUES (@QuestionId, @PartnerId, @AnswerVal)
END
The reason for the condition is because the input will be in 1 of 2 forms:
@AnswerId
will beNULL
(the input corresponds to an answer that has not yet been submitted) and the other values will be defined. The other values are needed to@AnswerId
will be non-NULL
and the other values will be defined although@PartnerId
and@QuestionId
are irrelevant for the update because that information is already within the table relations.
First question: Is that sproc
the most efficient way of doing an "Add or Update"? Is it possible to do an "Add or Update" that brings in all the items at once? Because, you see, I'm calling this on each item.
The controller I'm using to handle the AJAX request that passes in the JavaScript object is
[HttpPost]
public ActionResult SubmitAnswers ( List<AnswerSubmission> Answers )
{
bool goodSoFar = true;
string status = "Answers submitted successfully";
try
{
this._Db.SubmitAnswers(Answers, this._Pid);
}
catch ( Exception e )
{
goodSoFar = false;
status = String.Format("Exception occured during answer submission: {0}", e.Message);
}
return Json(new { Succeeded = goodSoFar, Message = status } );
}
where AnswerSubmission
is defined by
public class AnswerSubmission
{
public int? AnswerId { get; set; }
public int? AnswerVal { get; set; }
public int QuestionId { get; set; }
}
The function SubmitAnswers
looks like
public void SubmitAnswers ( List<AnswerSubmission> Answers, Guid PartnerId )
{
try
{
foreach ( AnswerSubmission A in Answers )
{
using ( SqlCommand cmd = new SqlCommand("AddOrUpdateAnswer", this._Conn) )
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@AnswerId", A.AnswerId);
cmd.Parameters.AddWithValue("@AnswerVal", A.AnswerVal);
cmd.Parameters.AddWithValue("@QuestionId", A.QuestionId);
cmd.Parameters.AddWithValue("@PartnerId", PartnerId);
this._Conn.Open();
cmd.ExecuteNonQuery();
this._Conn.Close();
}
}
} catch ( Exception ) { throw; }
}
Second question: Is that the correct way, with an Open
ing and then Close
ing of the connection for each item? That seems like it would be inefficient. Is there a better way?
Third question: How do I debug an AJAX method like this? I've set up breakpoints all over the place in my controller, but none of them are getting hit. The exception that is getting thrown, which I see in the object returned by the success
function of my JavaScript, says
"Exception occured during answer submission: Object reference not set to an instance of an object."
but doesn't point me to any line in my code. So I have no idea which object reference is not set to an instance of an object.
Any help greatly appreciated here.