Asp.net Transaction with foreach loop - asp.net-mvc

I am trying to save one Gridview with two checkbox in database with Asp.net Transaction , I am Getting Error when same condition come
SqlCommand cmd = new SqlCommand("procedure", con);
SqlCommand cmd1 = new SqlCommand("procedure1", con);
foreach (GridViewRow row in gvrecept.Rows)
{
if (cash.Checked){
cmd.Parameters.AddWithValue("#parameter", "value");
cmd.Transaction = trns;
}
else if (cheque.Checked)
{
cmd1.Parameters.AddWithValue("#parameter1", "value1");
cmd1.Transaction = trns;
}
}
int i = cmd1.ExecuteNonQuery();
int j = cmd.ExecuteNonQuery();
if (i > 0 && j > 0 )
{
trns.Commit();
}

As explained in my comment above you need to change something:
The trns should be added outside the loop just one time together with the setting to CommandType = CommandType.StoredProcedure and the creation of the two commands.
Inside the loop you should execute the command at each loop for each row you traverse. Also it is not clear if the two commands are mutually exclusive. I mean, if you have two checkboxes set then you should execute both commands but not if you don't have the matching checkbox set. If this is the case you need to use two separate ifs not an else if.
Notice that inside the loop you can simply change the value of the parameter before executing the command. This will be a smaller optimization but nevertheless it is simpler than creating the command or clearing the parameter collection at each loop.
Finally the commit of the Transaction should be done outside the loop when you have completed the insertion. If you have an error then an exception occurs and the Commit is skipped.
Final note. It is not clear why you need two commands at all. In the code above you use always the same StoredProcedure but passing different values. If this is the case then one command will do just fine.
SqlCommand cmd = new SqlCommand("procedure1", con);
cmd.Transaction = trns;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#parameter", SqlDbType.NVarChar);
SqlCommand cmd1 = new SqlCommand("procedure1", con);
cmd1.Transaction = trns;
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.Add("#parameter1", SqlDbType.NVarChar);
foreach (GridViewRow row in gvrecept.Rows)
{
if (cash.Checked)
{
cmd.Parameters["#parameter"].Value = "value";
cmd.ExecuteNonQuery();
}
if (cheque.Checked)
{
cmd.Parameters["#parameter1"].Value = "value1";
cmd1.ExecuteNonQuery();
}
}
trns.Commit();

Related

Database.ExecuteSqlCommand returns incorrect rowcount

I'm using context.Database.ExecuteSql to update a table. The update with where clause is executed correctly and the record is updated. However the method returns 2 for rowcount instead of 1. When I execute the update statement in SSMS, the result rowcount returned is 1. Can someone provide insight on this?
string query =
string.Format("update {0} set Description = '{1}', Code = '{2}', LastUpdatedBy = '{3}', LastUpdatedDate = '{4}' where ID = {5};",
tableName,
description,
code,
lastUpdatedBy,
lastUpdatedDate,
ID);
int rowCount = 0;
string message = string.Empty;
using (DBContext context = new DBContext())
{
rowCount = context.Database.ExecuteSqlCommand(TransactionalBehavior.EnsureTransaction, query);
}
return rowCount == 0 ? //this return 2 instead of 1.
new SaveResult(SaveResult.MessageType.Error, string.Format("There was an error updating a record in the {0} table.", tableName), "Index") :
new SaveResult(SaveResult.MessageType.Success, string.Format("The update of {0} was successful.", tableName), "Index");
This returns rowcount = 1 in SSMS:
update zAddressTypes
set Description = 'Current', Code = '101122', LastUpdatedBy = 'user', LastUpdatedDate = '10/20/2014 12:17:26 PM'
where ID = 1;
DECLARE #RowCount INTEGER = ##ROWCOUNT;
select #RowCount;
The rowcount is being returned separately. What you are seeing here is the exit status of the query.
ExecuteSqlCommand return value is for the status of query not for row count. You may want to look into using a datareader or something similar to return the rowcount.
It is the way the datacontext works, see this link:
Entity Framework: Database.ExecuteSqlCommand Method
Apparently the command is updating two records.
Do you have a trigger on your table? I confirmed this behavior can be caused by a trigger as the rows affected by the trigger are added to the row count affected by your SQL command. I commonly check for a 0 or >0 return value to know if anything was affected. You could also return an output variable if you're calling a stored procedure.

Is there any way get datarow from datatable without using foreach

Controller
foreach (DataRow temp in act.Rows)
{
_oResolutionModel.activityNo = temp["ActivityID"].ToString();
_oResolutionModel.assignTechnician = temp["TechNo"].ToString();
_oResolutionModel.recommendation = temp["RECOMMENDATION"].ToString();
_oResolutionModel.jobStart = (DateTime)temp["JobStart"];
_oResolutionModel.jobEnd = (DateTime)temp["JobEnd"];
_oResolutionFacade.setResolutionID(_oResolutionModel.activityNo);
DataTable res = _oResolutionFacade.getResolution(_oAppSetting.ConnectionString);
foreach (DataRow x in res.Rows)
{
_oResolutionModel.solution = x["Resolution"].ToString();
_oResolutionModel.remarks = x["Remarks"].ToString();
_oResolutionList.Add(_oResolutionModel);
break;
}
_oResolutionList.Add(_oResolutionModel);
break;
}
In here my _oResolutionList count = 1, meaning there's two data in it and it duplicated the first data. I want to have only 1 data in my _oResolutionList. Do I need to add some code in my inner Foreach or should I change something on it.?
Or You can suggest me how to delete the second data entry.?
Instead of using a foreach loop. You can also check the nullity first and then assign.
You can also do :
_oResolutionFacade.setResolutionID(_oResolutionModel.activityNo);
DataTable res = _oResolutionFacade.getResolution(_oAppSetting.ConnectionString);
_oResolutionModel.solution = res.Rows[0]["Resolution"].ToString() ?? string.Empty; //To make sure that if it is null it will assign to an empty string
_oResolutionModel.remarks = res.Rows[0]["Remarks"].ToString()?? string.Empty;
You have many solutions to deal with that.
Hope it will help you

The INSERT INTO statement contains the following unknown field name: 'a'. Make sure you have typed the name correctly, and try the operation again

// e,g, I want to insert 3 columns in 1st row and 10 columns in rest of the rows
//I am Creating excel file with sheet name as MySheet
// then updating value in 1st row, 1st cell of header as blank
//then inserting data
// Can anyone please help to insert data in excel without header
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName +
";Mode=ReadWrite;Extended Properties=\"Excel 12.0 XML;HDR=NO\"";
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "CREATE TABLE [MySheet] (a string)";
cmd.ExecuteNonQuery();
cmd.CommandText = "UPDATE [MySheet$] SET F1 = \"\"";
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO [MySheet] (a) values ('ABC')" //<-----Getting error to insert
cmd.ExecuteNonQuery();
}
}
conn.Close();
Just try [removed the (a)]
cmd.CommandText = "INSERT INTO [MySheet] values ('ABC')";
I get the same error. There was a padded space ending column name in Excel. Removing that space from end of column name fixed the issue.

Getting Uncommitted Transactions Sqlite With System.Data.Sqlite

I am trying to get a count of uncommitted records in a SQLite database using the System.Data.Sqlite library. My research thus far has pointed towards using the PRAGMA read_committed, but I always get a count of 0 until records are committed. Any tips?
using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + this.Path))
{
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn))
{
cmd.CommandText = "PRAGMA read_uncommitted = true;";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT Count() FROM Tiles WHERE TileLayerId = " + tileLayerId;
return Convert.ToInt32(cmd.ExecuteScalar());
}
}

sp_getProcedureColumns

I have tried to pass in the proc name into procedureNamePattern and the procedure seems to return all the metadata for all the procedures. I pass in a empty string and I get the same results.
The following is the code used:
using (AdsCommand command = new AdsCommand { CommandText = "sp_getProcedureColumns",
Connection = connection,
CommandType = CommandType.StoredProcedure })
{
AdsParameter param = new AdsParameter("#procedureNamePattern", DbType.String) {
Direction = ParameterDirection.Input, Value = originalProcedureName };
command.Parameters.Add(param);
AdsParameter param0 = new AdsParameter("#catalog", DbType.String) {
Direction = ParameterDirection.Input, Value = null };
command.Parameters.Add(param0);
AdsParameter param1 = new AdsParameter("#schemaPattern", DbType.String) {
Direction = ParameterDirection.Input, Value = null };
command.Parameters.Add(param1);
AdsParameter param2 = new AdsParameter("#columnNamePattern", DbType.String) {
Direction = ParameterDirection.Input, Value = null };
command.Parameters.Add(param2);
With stored procedures, you can use the DeriveParameters method. That might make it simpler. The following is an example:
AdsCommand cmd = conn.CreateCommand();
cmd.CommandText = "sp_getProcedureColumns";
cmd.CommandType = CommandType.StoredProcedure;
cmd.DeriveParameters();
cmd.Parameters["ProcedureNamePattern"].Value = "MyProcName";
AdsDataReader rdr = cmd.ExecuteReader();
If you do not call the DeriveParameters method, then the underlying SQL statement that is generated is produced directly from the provided parameters in the given order. That means you would need to provide the parameters in the order to match the procedure definition. In this case, the ProcedureNamePattern parameter needs to be 3rd. If you change the order of the cmd.Parameter.Add() calls, then your original example should work.

Resources