My dataset doesn't work properly - c#

My problem is that when it gets updated it adds the previous data which was in it Again and again
and i use a telerik grid view
here my code in 3 layers
first one
private void btnSbmt_Click(object sender, EventArgs e)
{
foreach (var row in radGridView1.Rows)
{
_MyName.Add((string)row.Cells[1].Value);
}
foreach (var row in radGridView1.Rows)
{ // 0 - first column
_MyAmount.Add((int)row.Cells[2].Value);
}
foreach (var row in radGridView1.Rows)
{
_MyPrice.Add((decimal)row.Cells[3].Value);
}
Ref_View_Model = new View_model._View_Model();
Ref_View_Model.GetInsertProduct(_myName, _myAmount, _myPrice, txtDt.Text);
radGridView1.CurrentRow.Delete();
productTableAdapter.Update(sales_and_Inventory_SystemDataSet);
productTableAdapter.Fill(sales_and_Inventory_SystemDataSet.Product);
MessageBox.Show("Product(s) were added", "Done", MessageBoxButtons.OK);}
second one
public void GetInsertProduct( List<string> _name, List<int> _amount, List<decimal> _price, string _date)
{
Ref_Model = new Model._Model();
Ref_Model.InsertProduct( _name, _amount, _price, _date);
}
and the Third one
public void InsertProduct(List<string> _myName,
List<int> _myAmount,
List<decimal> _myPrice, string _date)
{
Connection_String = myconnection string
Query = #"INSERT INTO dbo.product(Name, Amount, Price, [date])
VALUES(#Name, #Amount, #Price, #Date);";
using ( Con = new SqlConnection(Connection_String))
using ( Cmd = new SqlCommand(Query, Con))
{
Cmd.Parameters.Add("#Name", SqlDbType.NVarChar);
Cmd.Parameters.Add("#Amount", SqlDbType.Int);
Cmd.Parameters.Add("#Price", SqlDbType.Decimal);
// Cmd.Parameters.Add("#Date", SqlDbType.NVarChar);
Cmd.Parameters.Add("#Date", SqlDbType.DateTime).Value = Convert.ToDateTime(_date);
Cmd.Connection = Con;
Con.Open();
int recordsToAdd = _myName.Count();
for(int x = 0; x < recordsToAdd; x++)
{
Cmd.Parameters["#Name"].Value = _myName[x];
Cmd.Parameters["#Amount"].Value = _myAmount[x];
Cmd.Parameters["#Price"].Value = _myPrice[x];
Cmd.Parameters["#Date"].Value = _date;
Cmd.ExecuteNonQuery();
}
}
}

It seems that you are using global variables to keep the values that you read from the grid. If you don't clear them after the first insert, you have still the values in the global lists and you add them again to the datatable
Of course you can use just one loop to reload the global variables with the actual values present in the grid
private void btnSbmt_Click(object sender, EventArgs e)
{
// This removes whatever is in the lists
_MyName.Clear();
_MyAmount.Clear();
_MyPrice.Clear();
// and now start adding items from scratch
foreach (var row in radGridView1.Rows)
{
_MyName.Add((string)row.Cells[1].Value);
_MyAmount.Add((int)row.Cells[2].Value);
_MyPrice.Add((decimal)row.Cells[3].Value);
}
....

Related

This C# / sql query code takes a lot of time to update the table

Can anyone help improve performance? Updating the table takes a lot of time.
I am updating the serial number from datagridview to a table called dbo.json
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
string VAL1;
string VAL2;
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
if (string.IsNullOrEmpty(row.Cells[5].Value as string))
{
}
else
{
for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
var cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
using (var con = new SqlConnection(cnn))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2";
cmd.Parameters.AddWithValue("#VAL1", VAL1);
cmd.Parameters.AddWithValue("#VAL2", VAL2);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
MessageBox.Show("dbo.json is ready");
}
You shouldn't create the connection and command inside such a tight loop - create and open the connection and command ONCE before the loop, and in the loop, only set the parameter values and execute the query for each entry.
Something like this:
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
string VAL1;
string VAL2;
// define connection string, query text *ONCE* before the loop
string cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
string updateQuery = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2;";
// create connection and command *ONCE*
using (SqlConnection con = new SqlConnection(cnn))
using (SqlCommand cmd = new SqlCommand(updateQuery, cnn))
{
// Define parameters - adapt as needed (don't know the actual datatype they have)
cmd.Parameters.Add("#VAL1", SqlDbType.VarChar, 100);
cmd.Parameters.Add("#VAL2", SqlDbType.VarChar, 100);
// open connection ONCE, for all updates
con.Open();
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
{
if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
{
for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
// set the values
cmd.Parameters["#VAL1"].Value = VAL1;
cmd.Parameters["#VAL2"].Value = VAL2;
// execute query
cmd.ExecuteNonQuery();
}
}
}
// close connection after all updates are done
con.Close();
}
MessageBox.Show("dbo.json is ready");
}
Create the connection ONCE...you're creating a new database connection each time through the loop! And in fact you do not need to create new command objects each time. You can reuse the command object because the parameters are the same. Just clear the params each time through the loop.
Also don't do the grid view count in the loop, set a variable for it.
string query = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2";
int counter = DgvWhistlSorted.Rows.Count - 2;
using (SqlConnection con = new SqlConnection(cnn))
{
con.Open();
using(SqlCommand cmd = new SqlCommand(cnn,query))
{
cmd.Parameters.Clear();
//Do your loop in here
for (int i = 0; i <= counter; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
cmd.Parameters.AddWithValue("#VAL1", VAL1);
cmd.Parameters.AddWithValue("#VAL2", VAL2);
cmd.ExecuteNonQuery();
}
}
}
A better idea is to do this in one command, by passing all the data in a Table-Value Parameter (TVP):
First create the table type. I don't know your data types, so I'm guessing here. Make sure to match the types to the existing table.
CREATE TYPE dbo.OrderJson (
Order int PRIMARY KEY,
RowN nvarchar(max) NOT NULL
);
Then you can pass the whole thing in one batch. You need to create a DataTable to pass as the parameter, or you can use an existing datatable.
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
var table = new DataTable {
Columns = {
{ "Order", typeof(int) },
{ "RowN", typeof(string) },
},
};
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
table.Rows.Add(DgvWhistlSorted.Rows[i].Cells[0].Value, DgvWhistlSorted.Rows[i].Cells[6].Value)
const string query = #"
UPDATE dbo.json
SET RowN = t.RowN
FROM dbo.json j
JOIN #tmp t ON t.order = j.[A-order];
";
using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["sql"].ConnectionString))
using (var cmd = new SqlCommand(query, con))
{
cmd.Parameters.Add(new SqlParameter("#tmp", SqlDbType.Structured) { Value = table, TypeName = "dbo.OrderJson" });
con.Open();
cmd.ExecuteNonQuery();
}
MessageBox.Show("dbo.json is ready");
}
I found that the fastest way would be to save the DATAGRIDVIEW to an SQL table and continue the process with - stored procedure + update query - between two tables - now it flies ...
Thank you all

How to retrieve Distinct string values from comparing two Arrays?

I want to retrieve Absent student names from sql database.
I have a Listbox in which i have Present student Rfid data (Something like 42 39 A0 11), I have stored the student details along with Rfid in database as nvarchar(1500) datatype.
Using the present stud id in list box i want to retrieve absent students name in an List.
Then i thought of using foreach loop to remove the students who's id was in the Listbox
But when i defined the two list like total and present with values and tried to remove the string from total which are in present the nthe output was successful
private void checkabst_Click(object sender, EventArgs e)
{
string[] present1 = new string[listbox_present.Items.Count];
List<string> present = new List<string> { ""};
List<string> absent = new List<string>();
List<string> total = new List<string>();
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("Select Rfid_Uid From Studetails", con);
con.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
total.Add(sdr[0].ToString());
}
}
present = listbox_present.Items.Cast<string>().ToList();
foreach(string temp in present)
{
total.Remove(temp);
}
foreach (string temp in total)
{
listbox_absent.Items.Add(temp);
}
}
Stuck here from past few days.
The problem i think the listbox values are giving trouble while removing the string from total list.
From your comments in Ehsan's answer above I am not sure you know about:
System.Linq.Enumerable.Distinct
You can achieve this simply by an Except method. No need to for loops
Remove following code
bool isfound = false;
for (int i = 0; i < 3; i++)
{
isfound = false;
for (int j = 0; j < present.Length; j++)
{
if (allstd[i] == present[j])
{
isfound = true;
}
}
if (!isfound)
{
MessageBox.Show(allstd[i]);
}
}
and add
absent = allstd.Except(present).ToArray();
and iterate over these to show in MessageBox.
foreach (var stud in absent)
{
MessageBox.Show(stud);
}
Just to clarify after OP comment , Give a working example
string[] present = { "A" , "C" , "D" ,"P"};
string[] absent = new string[3];
string[] allstd = { "A", "B", "C" ,"D" , "E" , "P"};
absent= allstd.Except(present).ToArray();
absent will contain "B" and "E"
Update after OP's latest code update.
Try replacing your method with following method with removed tow foreach loops
private void checkabst_Click(object sender, EventArgs e)
{
string[] present1 = new string[listbox_present.Items.Count];
List<string> present = new List<string> { ""};
List<string> absent = new List<string>();
List<string> total = new List<string>();
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("Select Rfid_Uid From Studetails", con);
con.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
total.Add(sdr[0].ToString());
}
}
present = listbox_present.Items.Cast<string>().ToList();
absent = total.Except(present).ToArray();
foreach (var stud in absent)
{
MessageBox.Show(stud);
}
}

C# - SQL Insert Value and ID of checkbox From CheckboxList

The Issue:
I populate a checkbox list from a SQL table:
public static List<string> populateCheckBoxes(string type)
{
List<string> items = new List<string>();
items.Add("");
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand sqlcmd;
switch (type)
{
case "referralorsignposting":
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment WHERE type = 'Referral or Signposting' ORDER BY order_no, name", conn);
break;
case "actionstaken":
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment WHERE type = 'Actions Taken' ORDER BY order_no, name", conn);
break;
default:
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment", conn);
break;
}
SqlDataAdapter da = new SqlDataAdapter(sqlcmd);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
items.Add(dr["name"].ToString());
CheckboxIDRecord = dr["id"].ToString();
//items.Add(dr["VisitTime"] + " " + dr["PropPostcode"]);
}
return items;
}
I have iterated through each value that is selected in the "checkboxlist" and this inserts each value selected:
foreach (var item in saw.actionsTakenCheckBoxList)
{ //ADD ACTIONS AND REFERRAL
SqlCommand add = new SqlCommand("INSERT INTO SWApp_CheckboxAnswers (SW_ID, Checkbox_ID, Checkbox_Section, Checkbox_Type, Checkbox_Answer) VALUES(#SW_ID,#Checkbox_ID,#Checkbox_Section,#Checkbox_Type,#Checkbox_Answer) ");
add.CommandType = CommandType.Text;
add.Connection = sqlcon;
add.Parameters.AddWithValue("#SW_ID", "");
add.Parameters.AddWithValue("#Checkbox_ID", "");
add.Parameters.AddWithValue("#Checkbox_Section", "");
add.Parameters.AddWithValue("#Checkbox_Type", "");
add.Parameters.AddWithValue("#Checkbox_Answer", "");
add.Parameters["#SW_ID"].Value = saw.EntryID.ToString();
add.Parameters["#Checkbox_ID"].Value = CheckboxIDRecord.ToString();
add.Parameters["#Checkbox_Section"].Value = "SmokeDetectionReferral";
add.Parameters["#Checkbox_Type"].Value = "";
add.Parameters["#Checkbox_Answer"].Value = item.ToString();
sqlcon.Open();
add.ExecuteNonQuery();
sqlcon.Close();
}
As you can see what i have currently tried only inputs the ID for the first value selected in the Checkboxlist.
The Aim:
The aim is to have insert the value of the checkbox which is "name" and also the "id" of the each item.
Research:
I tried following this article to put the items into an array but ended up with a 'Array was out of bounds of the index' which led me to the second article.
Pass items from checkboxlist to SQL Server table
Index was out of bounds of array? c# forms
I would appreciate any guidance with this. Thanks.
I see several issues, rather than attempting to rectify them here is a proposal for how to work this out.
The overall picture can be seen in my MSDN code sample on CheckedListBox and SQL-Server which includes an sql script to generate the datbase and data.
https://code.msdn.microsoft.com/Working-with-CheckedListBox-3b765442?redir=0
Taken from the link above in Operations.cs, this method gets our data (next code block populates the CheckedListBox)
/// <summary>
/// Get all records to show in the CheckedListBox
/// </summary>
/// <returns></returns>
public DataTable GetAll()
{
var dt = new DataTable();
using (SqlConnection cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (SqlCommand cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT id, Description, Quantity, CheckedStatus FROM Products ---WHERE (Quantity > 0)";
cn.Open();
dt.Load(cmd.ExecuteReader());
}
}
return dt;
}
Form code
/// <summary>
/// Load CheckedListBox from database table
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
var ops = new Operations();
// read data from database table
var dt = ops.GetAll();
int LastIndex = 0;
/*
* Here we iterate the rows in the DataTable while in
* CoursesCodeSample I set the DataSource of the CheckedListBox
* to the DataTable. The method shown here has always been the
* way to go as many indicated that since the DataSource property
* of the CheckedListBox is not documented it could go away, well
* many years later it's still here so guess what, it's okay.
*/
foreach (DataRow row in dt.Rows)
{
checkedListBox1.Items.Add(new CheckListBoxItem()
{
Description = row.Field<string>("Description"),
PrimaryKey = row.Field<int>("id"),
Quantity = row.Field<int>("Quantity"),
IsDirty = false
});
LastIndex = checkedListBox1.Items.Count - 1;
checkedListBox1.SetItemChecked(LastIndex, row.Field<bool>("CheckedStatus"));
}
checkedListBox1.ItemCheck += CheckedListBox1_ItemCheck;
}
From Opertions.cs - insertion method
public void Insert(List<CheckListBoxItem> items)
{
// optionally used for obtaining new primary key
//int newIdentifier;
using (SqlConnection cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (SqlCommand cmd = new SqlCommand { Connection = cn })
{
// uncomment ending select statement and use commented to get new primary key
cmd.CommandText = "INSERT INTO Products " +
"([Description],Quantity,CheckedStatus) " +
"VALUES (#Description,#Quantity,#CheckedStatus); " +
"-- SELECT CAST(scope_identity() AS int);";
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#Description", SqlDbType = SqlDbType.NVarChar });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#Quantity", SqlDbType = SqlDbType.Int });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#CheckedStatus", SqlDbType = SqlDbType.Bit });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#CategoryIdentifier", SqlDbType = SqlDbType.Int });
cn.Open();
foreach (CheckListBoxItem item in items)
{
cmd.Parameters["#Description"].Value = item.Description;
cmd.Parameters["#Quantity"].Value = item.Quantity;
cmd.Parameters["#CheckedStatus"].Value = item.Checked;
//newIdentifier = (int)cmd.ExecuteNonQuery();
if ((int)cmd.ExecuteNonQuery() > -1)
{
// inserted
}
else
{
// failed
}
}
}
}
}
The above is basic, the commented out code shows (if needed) how to get the new primary key.
Call the method above
private void iterateButton_Click(object sender, EventArgs e)
{
var items = new List<CheckListBoxItem>();
for (int index = 0; index < checkedListBox1.Items.Count; index++)
{
if (((CheckListBoxItem)checkedListBox1.Items[index]).IsDirty)
{
items.Add(new CheckListBoxItem()
{
PrimaryKey = ((CheckListBoxItem)checkedListBox1.Items[index]).PrimaryKey,
Checked = checkedListBox1.GetItemChecked(index),
Description = ((CheckListBoxItem)checkedListBox1.Items[index]).Description
});
}
}
if (items.Count >0)
{
Ops.Insert(items);
}
}
Finally the class used to populate the CheckedListBox
namespace CheckListBoxFromSQL_Server
{
public class CheckListBoxItem
{
/// <summary>
/// Identifier for database table
/// </summary>
public int PrimaryKey;
/// <summary>
/// Display member for CheckedListBox and a field in the table
/// </summary>
public string Description;
public int Quantity;
/// <summary>
/// Indicates the checked state in the database table and for setting a Checked item in the CheckedListbox
/// </summary>
public bool Checked;
/// <summary>
/// Used to determine if a item changed after loaded in the CheckedListBox
/// </summary>
public bool IsDirty;
public override string ToString() { return Description; }
}
}
Hope this is helpful
I implemented a dictionary for the items to be placed into the checkboxlist. This allows me to use the value within the checkbox items and then use the Key in the INSERT to the SQL DB.
Dictionary<string, string> referral = new Dictionary<string, string>();
On form load populate the checkboxlist with items from dictionary.
private void Section3_Load(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("select Id, name from SWApp_List_Equipment WHERE type = 'referral or signposting' ORDER BY order_no,name", conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
referral.Add(dr["id"].ToString(), dr["name"].ToString());
}
}
foreach (KeyValuePair<string, string> refs in referral)
{
box = new CheckBox();
box.Text = refs.Value.ToString();
actionsTakenCheckBoxList.Items.Add(box.Text);
box.CheckedChanged += new EventHandler(this.CheckedChange);
}
}
Insert values into table on Close Button of form.
private void closeButton_Click(object sender, EventArgs e)
{
using (SqlConnection sqlcon = new SqlConnection(connectionString)) {
//summary
foreach (var item in actionsTakenCheckBoxList.CheckedItems.OfType<string>().ToList())
{
//ADD ACTIONS AND REFERRAL
SqlCommand add = new SqlCommand("INSERT INTO SWApp_CheckboxAnswers (SW_ID, Checkbox_ID, Checkbox_Section, Checkbox_Type, Checkbox_Answer) VALUES(#SW_ID,#Checkbox_ID,#Checkbox_Section,#Checkbox_Type,#Checkbox_Answer) ");
add.CommandType = CommandType.Text;
add.Connection = sqlcon;
add.Parameters.AddWithValue("#SW_ID", "");
add.Parameters.AddWithValue("#Checkbox_ID", "");
add.Parameters.AddWithValue("#Checkbox_Section", "");
add.Parameters.AddWithValue("#Checkbox_Type", "");
add.Parameters.AddWithValue("#Checkbox_Answer", "");
add.Parameters["#SW_ID"].Value = entry.entryID.ToString();
var myKey = referral.FirstOrDefault(x => x.Value == item.ToString()).Key;
add.Parameters["#Checkbox_ID"].Value = myKey;
add.Parameters["#Checkbox_Section"].Value = "SmokeDetection";
add.Parameters["#Checkbox_Type"].Value = "Referral";
add.Parameters["#Checkbox_Answer"].Value = item.ToString();
sqlcon.Open();
add.ExecuteNonQuery();
sqlcon.Close();
}
}
}

IndexOutOfBoundsException when debugging foreach statement

//I've list out the codes below, pls take a look and i'd appreciate if i can get some help. My program which is throwing index out of bound exception at line String studadmin = admin[g];
protected void Button1_Click(object sender, EventArgs e)
{
//retrieve studentdetails using List<String[];
List<String[]> stud = new List<String[]>();
int i = 0;
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox check = (CheckBox)row.FindControl("CheckBox1");
if (check.Checked)
{
String [] studDetail = new String [1];
studDetail[0] = row.Cells[1].Text;
stud.Add(studDetail);
}
i++;
}
int g = 0;
foreach (String[] admin in stud)
{
String studadmin = admin[g];
// here's whr the error are prompted (IndexOutOfBoundsException),
// when it reads the following "admin", the loop just ends here with an error;
try
{
myConnection = db.getConnection();
SqlCommand cmd = new SqlCommand("sp_IPPLOAssign");
cmd.Connection = myConnection;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#AcadYear", lb_AcadYear.Text);
cmd.Parameters.AddWithValue("#AcadPeriod", lb_AcadPeriod.Text);
cmd.Parameters.AddWithValue("#IPPProjID", lb_ProjID.Text);
cmd.Parameters.AddWithValue("#ProjSubID", "0");
cmd.Parameters.AddWithValue("#LOLoginID", ddl_LO.SelectedValue);
cmd.Parameters.AddWithValue("#LoginID", Session["UserID"].ToString());
cmd.Parameters.AddWithValue("#Adminno", studadmin);
myConnection.Open();
cmd.ExecuteNonQuery();
lb_Msg.Text = "Update Success.";
lb_error.Text = "";
}
catch (Exception ex)
{
share.WriteLog(ex.Message, "LOAssign.aspx", "Button1_Click()", "Error in updating LO.");
lb_error.Text = "Update failed.";
lb_Msg.Text = "";
}
finally
{
if (myConnection.State == ConnectionState.Open)
myConnection.Close();
}
g++; //loop the subsequent studadmin and store into database
}
refresh_gvCompany();
refresh_gvCurrent(); //refresh gridview
}
Have you confirmed your parameter names are exactly correct? Should #Adminno be #AdminNo, perhaps?
Every item in your stud is an array of String of size 1.
However, at every iteration you are increasing the index of array:
String studadmin = admin[g];
// ...
g++; // loop the subsequent studadmin and store into database
As the result, you actually try to access stud[0][0], stud[1][1]... the errors occurs here, because stud[1] contains only one item.
You need to remove i and g - they are both useless.
As your array only contains one item, it actually looks like you misunderstand usage of List and array. Probably, you want a List<string> instead of List<string[]>:
protected void Button1_Click(object sender, EventArgs e)
{
List<string> stud = new List<string>();
foreach (GridViewRow row in GridView1.Rows)
{
CheckBox check = (CheckBox)row.FindControl("CheckBox1");
if (check.Checked)
{
stud.Add(row.Cells[1].Text);
}
}
foreach (string studadmin in stud)
{
try
{
myConnection = db.getConnection();
SqlCommand cmd = new SqlCommand("sp_IPPLOAssign");
cmd.Connection = myConnection;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#AcadYear", lb_AcadYear.Text);
cmd.Parameters.AddWithValue("#AcadPeriod", lb_AcadPeriod.Text);
cmd.Parameters.AddWithValue("#IPPProjID", lb_ProjID.Text);
cmd.Parameters.AddWithValue("#ProjSubID", "0");
cmd.Parameters.AddWithValue("#LOLoginID", ddl_LO.SelectedValue);
cmd.Parameters.AddWithValue("#LoginID", Session["UserID"].ToString());
cmd.Parameters.AddWithValue("#Adminno", studadmin);
myConnection.Open();
cmd.ExecuteNonQuery();
lb_Msg.Text = "Update Success.";
lb_error.Text = "";
}
catch (Exception ex)
{
share.WriteLog(ex.Message, "LOAssign.aspx", "Button1_Click()", "Error in updating LO.");
lb_error.Text = "Update failed.";
lb_Msg.Text = "";
}
finally
{
if (myConnection.State == ConnectionState.Open)
myConnection.Close();
}
}
refresh_gvCompany();
refresh_gvCurrent();
}

C# search method

I'm having trouble coming up with the following search method:
public override List<Team> Search(Dictionary<string, string> prms, int pageSize, int page, out int results)
{
var tresults = new List<Team>();
string temp1 = "";
string temp2 = "";
using (SqlConnection conn = DB.GetSqlConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"Search";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach (KeyValuePair<string, string> pair in prms)
{
temp1 = pair.Key;
temp2 = pair.Value;
}
if (temp1 == "TeamName")
{
SqlParameter p1 = new SqlParameter("TeamName", System.Data.SqlDbType.VarChar);
p1.Value = temp2;
cmd.Parameters.Add(p1);
SqlParameter p2 = new SqlParameter("CityName", System.Data.SqlDbType.VarChar);
p2.Value = null;
cmd.Parameters.Add(p2);
}
else if (temp1 == "CityName")
{
SqlParameter p1 = new SqlParameter("TeamName", System.Data.SqlDbType.VarChar);
p1.Value = null;
cmd.Parameters.Add(p1);
SqlParameter p2 = new SqlParameter("CityName", System.Data.SqlDbType.VarChar);
p2.Value = temp2;
cmd.Parameters.Add(p2);
}
SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
}
}
//results = 1 + 1;
throw new NotImplementedException("Must be implemented by class. ");
}
What I'm trying to do is basically what this test is doing:
[TestMethod]
public void SearchForTeam()
{
var dic = new Dictionary<string, string>();
int total = 0;
dic.Add("TeamName", "Patriots");
var nd = new TeamRepository();
var teams = nd.Search(dic, 100, 1, out total);
Assert.IsTrue(teams.Find(p => p.TeamName == "Patriots") != null);
}
What I'm trying to do is have my method search by either Team Name (SQL column "TeamName", value "Patriots") or by City Name (SQL column "CityName" value "Chicago", etc. I think my issues mainly are that I'm not entirely sure if I'm understanding how the dictionary works.
Also, I'm not sure how the value I'm returning should work because I am both returning an int (from the out parameter) and type List. This is all pretty new to me, so its the basics that I don't quite understand I suppose.
How about this?
public override List<Team> Search(Dictionary<string, string> prms, int pageSize, int page)
{
var tresults = new List<Team>();
using (SqlConnection conn = DB.GetSqlConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"Search";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach (KeyValuePair<string, string> pair in prms)
cmd.Parameters.Add(new SqlParameter(pair.Key, System.Data.SqlDbType.VarChar) { Value = pair.Value });
SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
// I assume you'll use pageSize and page here?
}
}
return tresults; // I assume this is what you want to return.
}
If you don't want to use a specific column for your search, then there's no need to create a SqlParameter for that column and sets its Value to null -- just don't use that column!
Also, there's no need to have out int results. If you're returning the list of teams, then the invoker can just get the team count from the list (teams.Count). (If you are doing something else with results, then by all means ignore this paragraph.)
it's kind of hard to see what you are getting at here, I am unsure that you need a dictionary at all (would you pass in multiple records?)
personally I would do the below, the assumption is the stored procedure could handle the possibility of both parameters being populated if both are passed in completed.
public override List<Team> Search(string teamName,string cityName, int pageSize, int page)
{
var tresults = new List<Team>();
using (SqlConnection conn = DB.GetSqlConnection())
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"Search";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter p1 = new SqlParameter("TeamName", System.Data.SqlDbType.VarChar);
p1.Value = teamName;
cmd.Parameters.Add(p1);
SqlParameter p2 = new SqlParameter("CityName", System.Data.SqlDbType.VarChar);
p2.Value = cityName;
cmd.Parameters.Add(p2);
SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
while(reader.Read())
{
tresults.Add(BuildTeamFromReader(reader));
}
}
}
return tresults;
}
private Team BuildTeamFromReader(SqlDataReader reader)
{
var team = new Team();
team.TeamName = reader["TeamName"];//or whatever your column name is for team name
//ToDo other mappings
return team;
}

Categories

Resources