Reputation: 333
I am trying to insert data using a stored procedure that has two tables. This first table is data is through text boxes the second data is through a grid which I stored in the database and passed to be inserted. The problem is when reading datatable and inserting it says there are too many parameter which happens to add in the for loop. Any suggestion how to handle this as the SP? Thanks in advance.
CODE:
try
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = strConnection;
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandTimeout = 120;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "insFamilyDetails";
cmd.Parameters.AddWithValue("@strHusbandName", strHusbandName);
cmd.Parameters.AddWithValue("@strRelation", strRelation);
....
....
// Child Details
for (int i = 0; i < strChildredDetails.Rows.Count; i++)
{
cmd.Parameters.AddWithValue("@strChildName", strChildredDetails.Rows[i][0].ToString());
cmd.Parameters.AddWithValue("@strDOB", strChildredDetails.Rows[i][1]);
cmd.Parameters.AddWithValue("@strBaptisedon", strChildredDetails.Rows[i][2]);
cmd.Parameters.AddWithValue("@strFirstComOn", strChildredDetails.Rows[i][3]);
cmd.Parameters.AddWithValue("@strConfirmedOn", strChildredDetails.Rows[i][4]);
cmd.Parameters.AddWithValue("@strMarried", "0");
cmd.Parameters.AddWithValue("@strAlive", "1");
}
conn.Open();
ReturnValue = Convert.ToBoolean(cmd.ExecuteNonQuery());
conn.Close();
}
catch (Exception e)
{
DL_LogAppErrors(e.ToString(), System.Reflection.MethodBase.GetCurrentMethod().Name, "Insert Family Details");
return ReturnValue;
}
return ReturnValue;
Upvotes: 1
Views: 7351
Reputation: 360
I assume from the code you're going to add into a main table, and Child table. For this case, you need to separate the process into two:
EDIT: Using Transaction
con.Open();
SqlTransaction trans = con.BeginTransaction();
try {
// Execute the SP here
// After all SP executed, call the commit method
trans.Commit();
} catch (Exception ex) {
// An error happened, rollback
trans.RollBack();
}
con.Close();
Upvotes: 1
Reputation: 2895
As already said, you need to have ExecuteNonQuery inside for each loop, if you want to insert records of your grid.
Alternate option would be to Use Table Valued Paramter if you're using SQL Server 2008, that would make life more easy and you don't have to make round trip for each record of your gridview. Just pass the datatable.
Please check this link.
Edit:
For SQL Server 2005, you might want to use XML. Please check this link.
public string SerializeObject<T>(T Obj)
{
string strxml = string.Empty;
using (StringWriter sw = new StringWriter())
{
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.Serialize(sw, Obj);
strxml = sw.ToString();
}
return strxml;
}
Link contains above function, pass your datatable to this function, check out the generated XML and use same casing in stored procedure for elements in XML as XML is case sensitive.
Upvotes: 0
Reputation: 148110
You are adding parameters in command
in each iteration of the loop. After first iteration you are trying to add same parameter
name in parameter collection. You probably need to clear the collection of parameter on each iteration using SqlParameterCollection.Clear. Clear the parameter collection after executing command (In loop body).
conn.Open();
for (int i = 0; i < strChildredDetails.Rows.Count; i++)
{
cmd.Parameters.AddWithValue("@strChildName", strChildredDetails.Rows[i][0].ToString());
cmd.Parameters.AddWithValue("@strDOB", strChildredDetails.Rows[i][2]);
cmd.Parameters.AddWithValue("@strBaptisedon", strChildredDetails.Rows[i][2]);
cmd.Parameters.AddWithValue("@strFirstComOn", strChildredDetails.Rows[i][3]);
cmd.Parameters.AddWithValue("@strConfirmedOn", strChildredDetails.Rows[i][4]);
cmd.Parameters.AddWithValue("@strMarried", "0");
cmd.Parameters.AddWithValue("@strAlive", "1");
ReturnValue = Convert.ToBoolean(cmd.ExecuteNonQuery());
cmd.Parameters.Clear();
}
conn.Close();
If you have many records to insert in a table then you can send the comma separated values in SP and split then in SP and insert them. It will save db calls. This post will show how you can do that.
Upvotes: 1
Reputation: 978
For each row you want to insert you have to call the ExecuteNonQuery() function ie, it should be inside the for loop and after that clear the parameter collection at the end of loop.
conn.Open();
// Child Details
for (int i = 0; i < strChildredDetails.Rows.Count; i++)
{
cmd.Parameters.AddWithValue("@strHusbandName", strHusbandName);
cmd.Parameters.AddWithValue("@strRelation", strRelation);
....
....
cmd.Parameters.AddWithValue("@strChildName", strChildredDetails.Rows[i][0].ToString());
cmd.Parameters.AddWithValue("@strDOB", strChildredDetails.Rows[i][1]);
cmd.Parameters.AddWithValue("@strBaptisedon", strChildredDetails.Rows[i][2]);
cmd.Parameters.AddWithValue("@strFirstComOn", strChildredDetails.Rows[i][3]);
cmd.Parameters.AddWithValue("@strConfirmedOn", strChildredDetails.Rows[i][4]);
cmd.Parameters.AddWithValue("@strMarried", "0");
cmd.Parameters.AddWithValue("@strAlive", "1");
ReturnValue = Convert.ToBoolean(cmd.ExecuteNonQuery());
cmd.Parameters.Clear();
}
Upvotes: 0