Stored procedure not updating data - c#

I'm trying to pass a data table to a stored procedure. The table has four columns, OldDifficulty, OldIndex, NewDifficulty, and NewIndex. It is passed to a stored procedure which is supposed to update all the rows in a Puzzles table changing rows with the old index and difficulty to their new index and difficulty. The Puzzles table does not change, and I can't figure out why. I'm not sure whether the problem is in the code or in the database query.
Here is the C# code that calls the stored procedure:
var Form = context.Request.Form;
DataTable table = new DataTable();
table.Columns.Add("OldDifficulty");
table.Columns.Add("OldIndex");
table.Columns.Add("NewDifficulty");
table.Columns.Add("NewIndex");
foreach (var key in Form.Keys)
{
var Old = key.ToString().Split('_');
var New = Form[key.ToString()].Split('_');
if (Old == New || New.Length == 1 || Old.Length == 1) continue;
table.Rows.Add(Old[0], int.Parse(Old[1]), New[0], int.Parse(New[1]));
}
using (var con = new SqlConnection(SqlHelper.ConnectionString))
{
con.Open();
using (var com = new SqlCommand("RearrangePuzzles", con))
{
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add(new SqlParameter("ChangedPuzzles", table)
{ SqlDbType = SqlDbType.Structured });
com.ExecuteNonQuery();
}
con.Close();
}
and here is the stored procedure:
ALTER PROCEDURE [dbo].[RearrangePuzzles]
#ChangedPuzzles ChangedPuzzlesTable READONLY
AS
UPDATE p
SET
NthPuzzle = cp.NewIndex,
Difficulty = cp.NewDifficulty
FROM
Puzzles p JOIN
#ChangedPuzzles cp ON cp.OldIndex = p.NthPuzzle AND cp.OldDifficulty = p.Difficulty
Do you have any idea why the table isn't updating? Is there something wrong with my SQL?

Everything looks ok, except:
com.Parameters.Add(new SqlParameter("ChangedPuzzles", table)
{ SqlDbType = SqlDbType.Structured });
I would change to:
com.Parameters.Add(new SqlParameter("#ChangedPuzzles", table)
{ SqlDbType = SqlDbType.Structured });
# sign - prefix in parameter name.
Use SQL Server Profiler to see whether this query actually is executed.

check the order of fields in the table type ChangedPuzzlesTable , it must be same as datatable any change in order may cause this problem
check error by adding a try catch
try
{
using (var con = new SqlConnection(SqlHelper.ConnectionString))
{
con.Open();
using (var com = new SqlCommand("RearrangePuzzles", con))
{
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add(new SqlParameter("ChangedPuzzles", table)
{ SqlDbType = SqlDbType.Structured });
com.ExecuteNonQuery();
}
con.Close();
}
}
catch (Exception ex)
{
// ex will show you the error
}

Related

Stored procedure returns no rows with SqlDataAdapter

I'm new to using SqlDataAdpter and I'm trying to execute a stored procedure. The stored procedure executes successfully but no rows are returned. I've used SQL Server Profiler to monitor the call and it runs successfully (I can copy and execute the query from profiler without modifying it and get results).
I have the following:
public ActionResult Index()
{
SqlConnection conn = null;
DataSet results = null;
try
{
string connectionString = // ... my connection
conn = new SqlConnection(connectionString );
string query = #"usp_mySP";
conn.Open();
SqlDataAdapter sqlAdpt = new SqlDataAdapter(query, conn);
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
var dataDate = new SqlParameter { ParameterName = "#DataDate", Value = DateTime.Now };
var idList = new SqlParameter { ParameterName = "#IDList", Value = "1231,2324,0833" };
sqlAdpt.SelectCommand.Parameters.Add(dataDate);
sqlAdpt.SelectCommand.Parameters.Add(idList);
results = new DataSet();
sqlAdpt.Fill(results);
sqlAdpt.Dispose();
}
catch (SqlException e)
{
throw new Exception("Exception:" + e.Message);
}
finally
{
if (conn != null)
conn.Close();
}
return View(results);
}
When I inspect the DataSet through the debugger, it always returns 0 rows.
Please help with what I'm doing wrong?
Note: I've also tried (but do NOT prefer) executing as a SQL command:
EXEC usp_mySP #DataDate, #IDList
and it didn't work either as I got int to varchar conversion errors.
I think you try to add SqlParameter using SqlCommand like this :
SqlCommand cmd = new SqlCommand();
cmd.parameter.addwithvalue(#DataDate,DateTime.Now);
So the reason was because of set nocount on. I added it to my sp and it works. Thank you everyone for clarifying.

How to use stored procedure in C# to return a list of results?

Here is my stored procedure:
CREATE Proc UpdateChecklist
(
#TemplateId As INT
) as
begin
select MF.CheckListDataId from TemplateModuleMap TM
inner join ModuleField MF
on TM.ModuleId = MF.ModuleId
where TM.TemplateId = #TemplateId and MF.CheckListDataId not in
(select cktm.CheckListDataId from ChecklistTemplateMap cktm
inner join ChecklistData ckd
on cktm.CheckListDataId = ckd.Id
where cktm.TemplateId = #TemplateId)
end
So I expect to have a returned list of CheckListDataId here. I'm trying to use Database.ExecuteSqlCommand() but not succeed yet. How can I return a list of CheckListDataId here? Do I need to modify my stored proc? I'm pretty new to sql.
Any suggestion? This is an ASP.NET MVC 5 project
Your Stored Procedure will return you a resultset and you can process that however you want in your C#.
I would call the procedure from inside my model class in this way:
DataTable loadLogFilterData = SQLHelper.ExecuteProc(STORED_PROCEDURE_NAME, new object[] {
//Parameters to Stored Proc If Any
});
Then I have a SQLHelper Class inside which I create the SQL Connection and have the delegate methods to call the stored procedures.
public static DataTable ExecuteProc(string procedureName, Object[] parameterList, string SQLConnectionString) // throws SystemException
{
DataTable outputDataTable;
using (SqlConnection sqlConnection = OpenSQLConnection(SQLConnectionString))
{
using (SqlCommand sqlCommand = new SqlCommand(procedureName, sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
if (parameterList != null)
{
for (int i = 0; i < parameterList.Length; i = i + 2)
{
string parameterName = parameterList[i].ToString();
object parameterValue = parameterList[i + 1];
sqlCommand.Parameters.Add(new SqlParameter(parameterName, parameterValue));
}
}
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
DataSet outputDataSet = new DataSet();
try
{
sqlDataAdapter.Fill(outputDataSet, "resultset");
}
catch (SystemException systemException)
{
// The source table is invalid.
throw systemException; // to be handled as appropriate by calling function
}
outputDataTable = outputDataSet.Tables["resultset"];
}
}
return outputDataTable;
}
You have treat every output from a stored procedure as a resultset no matter what it contains. Then you need to manipulate that result set in your Model to populate the desired data structure and data type.

stored procedure in sql used in c#

I have used following stored procedure in sql:
alter procedure [dbo].[usp_Member_Org_OnGoingJobs]
(
#idUser varchar(50)
)
as
begin
declare #qry as varchar(max)
set #qry='select J.idJob,j.DateAdded,j.OpenedByWho,j.JobAddress ,j.final,j.idOrg,j.note
from Job J
inner join Users U on
U.idOrg=J.idOrg
where U.IdUser='+ #idUser+ '
and ISNULL(j.Final,'')=''
order by idJob'
execute(#qry)
end
GO
This stored procedure is formed sucessfully in sql.
But, When i tried to use them through asp.net c#, It gives me error:
Incorrect syntax near the keyword 'order'.
Everything seems correct.
Please tell me where i am making mistake??
Edit:
private void BindOnGoingJobs()
{
string sqlOnGoingJobs = "usp_Member_Org_OnGoingJobs";
DataTable dtJobList = new DataTable();
ArrayList paramList = new ArrayList();
paramList.Add(new ParamData("#idUser", Convert.ToString(Session["idUser"])));
dtJobList = obj.ExecuteProcedureAndGetDataTable(sqlOnGoingJobs, paramList);
grdOnGoingJobs.DataSource = dtJobList;
grdOnGoingJobs.DataBind();
paramList.Clear();
}
public DataTable ExecuteProcedureAndGetDataTable(string procedureName, ArrayList Parameters)
{
DataTable dt = new DataTable();
try
{
if (con.State != ConnectionState.Open)
con.Open();
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = procedureName;
cmd.Parameters.Clear();
foreach (ParamData p in Parameters)
{
cmd.Parameters.AddWithValue(p.pName, p.pValue);
}
da.SelectCommand = cmd;
da.Fill(dt);
con.Close();
return dt;
}
catch (Exception ex)
{
con.Close();
return dt;
}
}
You need to double your single quotes around the ISNULL check
set #qry='select J.idJob,j.DateAdded,j.OpenedByWho,j.JobAddress ,j.final,j.idOrg,j.note
from Job J
inner join Users U on
U.idOrg=J.idOrg
where U.IdUser='+ #idUser+ '
and ISNULL(j.Final,'''')=''''
order by idJob'
You need to escape the quotation mark by placing quotes 2 times like this.
and ISNULL(j.Final,'''')=''''
Check this blog post http://blog.sqlauthority.com/2008/02/17/sql-server-how-to-escape-single-quotes-fix-error-105-unclosed-quotation-mark-after-the-character-string/
Just add the table alias in order by, I guess should solve the issue
order by J.idJob

T-SQL Delete * from table then insert into table

Hello I'm trying to do following
Delete all from table X
insert desired values into table X
I thought then T-SQL would be way to achieve that because when something messes up in the INSERT command then everything will be deleted.
But this code does nothing it doesn't insert or delete the data. May someone help me to fix this issue?
spojeni.Open();
SqlTransaction sqlTrans = spojeni.BeginTransaction();
try
{
string delCmdTxt = "TRUNCATE TABLE PLODINY";
SqlCommand cmdDel = spojeni.CreateCommand();
cmdDel.CommandText = delCmdTxt;
cmdDel.Transaction = sqlTrans;
cmdDel.ExecuteNonQuery();
string insert_sql =
"INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(#PLODINA,#CENAZAQ,#MJ)";
SqlCommand sqlcom = spojeni.CreateCommand();
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
sqlcom.Parameters.AddWithValue("#PLODINA", row.Cells["PLODINA"].Value);
sqlcom.Parameters.AddWithValue("#CENAZAQ", row.Cells["CENAZAQ"].Value);
sqlcom.Parameters.AddWithValue("#MJ", row.Cells["MJ"].Value);
sqlcom.ExecuteNonQuery();
sqlcom.Dispose();
}
sqlTrans.Commit();
}
catch (System.Data.SqlClient.SqlException)
{
sqlTrans.Rollback();
}
finally
{
spojeni.Close();
spojeni.Dispose();
}
this.Close();
Your problem is in your foreach loop. You need to define your parameters before hand, and do not dispose the command object until you're all done with it. You can also use the Where extension method to filter out any invalid rows from your data source since its a UI element.
string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(#PLODINA,#CENAZAQ,#MJ)";
SqlCommand sqlcom = spojeni.CreateCommand();
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
sqlcom.Parameters.Add("#PLODINA");
sqlcom.Parameters.Add("#CENAZAQ");
sqlcom.Parameters.Add("#MJ");
// some validation - add what you need.
var validRows = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells["PLODINA"].Value != null);
foreach (DataGridViewRow row in validRows)
{
sqlcom.Parameters[0].Value = row.Cells["PLODINA"].Value;
sqlcom.Parameters[1].Value = row.Cells["CENAZAQ"].Value;
sqlcom.Parameters[2].Value = row.Cells["MJ"].Value;
sqlcom.ExecuteNonQuery();
}
sqlTrans.Commit();
sqlcom.Dispose();
You are doing your parameters totally wrong, because the only thing in your catch is the sqlTrans.Rollback(); you never see the errors you are getting, the first thing I would change is make that catch
catch (System.Data.SqlClient.SqlException)
{
sqlTrans.Rollback();
throw;
}
so you can now see the errors happen.
The next issue is if the table has any foreign key constraints your TRUNCATE TABLE will fail, if it is failing you can simply replace it with
string delCmdTxt = "delete from PLODINY";
SqlCommand cmdDel = spojeni.CreateCommand();
cmdDel.CommandText = delCmdTxt;
cmdDel.Transaction = sqlTrans;
cmdDel.ExecuteNonQuery();
As to why your inserts are not working, you are disposing the command every instance of the for loop, you are also trying to re-add the parameters every time, reformat that loop to the following
string insert_sql = "INSERT INTO PLODINY(PLODINA,CENAZAQ,MJ)VALUES(#PLODINA,#CENAZAQ,#MJ)";
using(SqlCommand sqlcom = spojeni.CreateCommand())
{
sqlcom.CommandText = insert_sql;
sqlcom.Transaction = sqlTrans;
sqlcom.Parameters.Add("#PLODINA", SqlDbType.NVarChar); //Replace with whatever the correct datatypes are
sqlcom.Parameters.Add("#CENAZAQ", SqlDbType.NVarChar);
sqlcom.Parameters.Add("#MJ", SqlDbType.NVarChar);
foreach (DataGridViewRow row in dataGridView1.Rows)
{
sqlcom.Parameters["#PLODINA"] = row.Cells["PLODINA"].Value;
sqlcom.Parameters["#CENAZAQ"] = row.Cells["CENAZAQ"].Value;
sqlcom.Parameters["#MJ"] = row.Cells["MJ"].Value;
sqlcom.ExecuteNonQuery();
}
}
sqlTrans.Commit();
However your code can be made even better, if your DataGridView was backed by a DataTable via binding you could use a SqlTableAdapter instead, Lets say you load the table from the database, display it on the grid, and then you want to push back the updated information. With a DataTable it would be as simple as
private string _getDataQuery = "select PLODINA, CENAZAQ, MJ from PLODINY";
public void GetData(DataTable data)
{
//You do not need to call open here as SqlDataAdapter does it for you internally.
using(var spojeni = new SqlConnection(GetConnectionString())
using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
{
data.Clear();
adapter.Fill(data);
}
}
public void UpdateData(DataTable data)
{
using(var spojeni = new SqlConnection(GetConnectionString())
using(var adapter = new SqlDataAdapter(_getDataQuery, spojeni)
using(var commandBuilder = new SqlCommandBuilder(adapter)
{
//This may or may not be nessesary for spojeni.BeginTransaction()
spojeni.Open();
using(var sqlTrans = spojeni.BeginTransaction())
{
adapter.SelectCommand.Transaction = sqlTrans;
adapter.UpdateCommand = commandBuilder.GetUpdateCommand();
adapter.UpdateCommand.Transaction = sqlTrans;
adapter.DeleteCommand = commandBuilder.GetDeleteCommand();
adapter.DeleteCommand.Transaction = sqlTrans;
adapter.InsertCommand = commandBuilder.GetInsertCommand()
adapter.InsertCommand.Transaction = sqlTrans;
try
{
adapter.Update(data);
sqlTrans.Commit();
}
catch
{
sqlTrans.Rollback();
throw;
}
}
}
}
Truncate Table only works if the table has not foreign key constraints... it's probably failing there and then rolling back the transaction in the catch statement...
Instead of Truncate try Delete From table and see if that fixes it...

Cannot find table 0 in dataset using stored procedures

I am not getting filled dataset after executing a stored procedure.
protected void btnsub_Click(object sender, EventArgs e)
{
ArrayList arInsert = ReturnParameter_insert();
DataSet dsInsertProfile = objadmin.GetGridData(arInsert, objconstant.sSP_INSERT_PROFILE);
if(int.Parse(dsInsertProfile.Tables[0].Rows[0].ItemArray[0].ToString())== 0)
{
lblThank.Text = "Your profile have been successfully saved.";
}
else
{
lblThank.Text = "Your profile is not saved, please try again later.";
}
}
public ArrayList ReturnParameter_insert()
{
ArrayList arProfile = new ArrayList();
Object[] c_first_name = new object[3] { "#strFname", "Varchar", (txtfname.Text != "") ? txtfname.Text : "" };
arProfile.Add(c_first_name);
return arProfile;
}
public DataSet GetGridData(ArrayList dbArray, string sSpName)
{
DataSet dsDataSet = new DataSet();
dsDataSet = datamanager.GetGridData(dbArray, sSpName);
return dsDataSet;
}
public static SqlDbType GetSqlDataType(string sDataType)
{
return (sDataType == "Integer") ? SqlDbType.Int : (sDataType == "Varchar") ? SqlDbType.VarChar : (sDataType == "Date") ? SqlDbType.Date : SqlDbType.BigInt;
}
public static DataSet GetGridData(ArrayList dbArray, string sSpName)
{
DataSet dsDataSet = new DataSet();
SqlConnection cn = createConnection();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sSpName;
object objPrMtrName;
object objSqlType;
object objPrMtrVal;
int i;
for (i = 0; i < dbArray.Count; i++)
{
objPrMtrName = ((object[])(dbArray[i]))[0];
objSqlType = ((object[])(dbArray[i]))[1];
objPrMtrVal = ((object[])(dbArray[i]))[2];
cmd.Parameters.Add(objPrMtrName.ToString(), GetSqlDataType(objSqlType.ToString())).Value = objPrMtrVal;
}
cmd.Connection = cn;
try
{
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(dsDataSet);
return dsDataSet;
}
catch (Exception ex)
{
throw ex;
}
finally
{
cn.Close();
cn.Dispose();
}
}
My stored procedure:
CREATE Procedure spInsert_profile
(#strFname varchar(200))
AS
BEGIN
INSERT INTO gdt_Users([c_first_name], [d_modified_dttm], [d_created_dttm])
VALUES(#strFname, GETDATE(), GETDATE())
END
Here I am using 3 tier, the same methods are working successfully for other pages but not for this particular code. The dataset in GETGRIDDATA method is filling null value. I am not able to find. Please help me....
you performing insert operation in your procedure than how is going to return to data Insert into statement does insert operation not retrieve operation.
...To retrieve data you need to call procedure with select * statement.
There is no select statement in your stored proc. adapter.fill() should recieve some sort of table from the stored proc's output.
From what I can see here you are executing a stored procedure that only performs an INSERT command, The reason you are getting a NULL value back is because a non query command such as UPDATE or INSERT will generally return only the number of rows affected e.g. 1 and not the data of the table you inserted to.
You would need to perform a SELECT command after the insert to get any data back.
The problem is in your stored procedure... you have to add select statement to the stored procedure for your return result in DataSet
Because you use Insert Into in your stored procedure.
Access based on Tables property:
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(dsDataSet);
var table1 = dsDataSet.Tables[0];
var table2 = dsDataSet.Tables[1];
Link : http://msdn.microsoft.com/fr-fr/library/system.data.dataset.tables.aspx

Categories