I'm selecting a DataView row based on a Tag value from a treeview. It Works fine most of the time, but under certain conditions does not return a record. I wrote the code below to test each row before I call the filter.
private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
if (treeView1.SelectedNode != null)
{
TreeNode tn = treeView1.SelectedNode;
Console.WriteLine(tn.Tag.ToString());
selectedTag = tn.Tag.ToString();
dv.Table = ds.Tables["ProductStruct"];
foreach (DataRow dr in dv.Table.Rows)
{
bool test = dr["uniqueID"].ToString() == tn.Tag.ToString();
Console.WriteLine(dr["uniqueID"].ToString() + " and " + tn.Tag.ToString() + test);
}
dv.RowFilter = "uniqueID = '" + tn.Tag.ToString() + "'";
Console.WriteLine(dv.RowFilter.ToString());
Console.WriteLine(dv.Count.ToString());
}
}
the output is as follows:
12331233-200-00e
12331233 and 12331233-200-00eFalse
12331233-100-000 and 12331233-200-00eFalse
12331233-200-00e and 12331233-200-00eTrue
12331233-300-000 and 12331233-200-00eFalse
12331233-400-000 and 12331233-200-00eFalse
12331233-500-000 and 12331233-200-00eFalse
12331233-600-000 and 12331233-200-00eFalse
12331233-700-000 and 12331233-200-00eFalse
12331233-800-000 and 12331233-200-00eFalse
12331233-900-000 and 12331233-200-00eFalse
uniqueID = '12331233-200-00e'
0
As you can see the bool test is true for one record but filter fails to return it. Any help is appreciated, I hate to use a loop where a single line should do the trick...
The loop you run overrides the value of the bool and loops as many times as the count of row exists in your table.
Inside the loop, use return to escape once you find the match. It will not go through all the rows. This will return only 1 value.
foreach (DataRow dr in dv.Table.Rows)
{
bool test = dr["uniqueID"].ToString() == tn.Tag.ToString();
if(dr["uniqueID"].ToString() == tn.Tag.ToString()){
Console.WriteLine(dr["uniqueID"].ToString() + " and " + tn.Tag.ToString() + test);
dv.RowFilter = "uniqueID = '" + tn.Tag.ToString() + "'";
return;
}
}
If you are expecting more matches, move the
dv.RowFilter = "uniqueID = '" + tn.Tag.ToString() + "'";
Inside the loop and encapsulate it with if statement.
foreach (DataRow dr in dv.Table.Rows)
{
bool test = dr["uniqueID"].ToString() == tn.Tag.ToString();
Console.WriteLine(dr["uniqueID"].ToString() + " and " + tn.Tag.ToString() + test);
if(dr["uniqueID"].ToString() == tn.Tag.ToString()){
dv.RowFilter = "uniqueID = '" + tn.Tag.ToString() + "'";
}
}
This will run the filter each time it finds a match.
I hope this helps.
Related
So, here it is my problem
I have four dropdowns in the screen, and all four are loaded when the screen loads, also when I change the first combobox, all three load with the selectedindex method, no problems in that.
But when I manually clear the first combobox, the remaining three retain the same values as before and I am not able to reset them. Any suggestions ?
private void comboBox_commodity_SelectedIndexChanged(object sender, EventArgs e)
{
//filter stat type
if (!comboBox_commodity.Text.Equals(""))
{
statTypes = new List<string>();
foreach (string groupID in groupIds)
{
string sql = "select [ERSStatisticType_Attribute] from " + schemaName + "ERSStatisticType_LU " +
"WHERE ERSStatisticType_ID IN (SELECT DISTINCT[ERSCommodity_ERSStatisticType_ID] FROM "
+ schemaName + "[ERSCommodityDataSeries] WHERE [ERSCommodity_ERSGroup_ID] = " + groupID
+ " and ERSCommoditySubCommodity_ID = " + getCommodityID(comboBox_commodity.Text) + " ) ";
DataTable dt = GetData(sql);
DataRow[] dr = dt.Select();
foreach (DataRow row in dr)
{
statTypes.Add(row["ERSStatisticType_Attribute"].ToString());
}
}
comboBox_statType.DataSource = statTypes;
comboBox_statType.SelectedItem = null;
//filter unit
//filter source
source = new List<string>();
foreach (string groupID in groupIds)
{
string sql = "select DISTINCT ERSSource_Desc from " + schemaName
+ "ERSSource_LU where ERSSource_ID IN (SELECT DISTINCT[ERSCommodity_ERSSource_ID] FROM " + schemaName + "[ERSCommodityDataSeries] WHERE [ERSCommodity_ERSGroup_ID] = " + groupID +
" and ERSCommoditySubCommodity_ID = " + getCommodityID(comboBox_commodity.Text) + " ) ORDER BY ERSSource_Desc";
DataTable dt = GetData(sql);
DataRow[] dr = dt.Select();
foreach (DataRow row in dr)
{
source.Add(row["ERSSource_Desc"].ToString());
}
}
comboBox_source.DataSource = source;
comboBox_source.SelectedItem = null;
unit = new List<string>();
foreach (string groupID in groupIds)
{
string sql = "select distinct ERSUnit_Desc from " + schemaName
+ "ERSUnit_LU ulu" + "," + schemaName + "ERSCommodityDataSeries cds" + "," + schemaName + "ERSDataValues dv " +
" where ulu.ERSUnit_ID=dv.ERSDataValues_ERSUnit_ID " +
" and cds.ERSCommoditySubCommodity_ID= " + getCommodityID(comboBox_commodity.Text) +
" and cds.ERSCommodity_ID=dv.ERSDataValues_ERSCommodity_ID " +
" and [ERSCommodity_ERSGroup_ID] = " + groupID;
DataTable dt = GetData(sql);
DataRow[] dr = dt.Select();
foreach (DataRow row in dr)
{
unit.Add(row["ERSUnit_Desc"].ToString());
}
}
comboBox1_unit.DataSource = unit;
comboBox1_unit.SelectedItem = null;
}
else
{
fillCommodityCombobox();
fillSourceCombobox();
fillUnitCombobox();
fillStatTypeCombobox();
}
}
If I manually clear the combobox, all other three values should be loaded with all the revelant values.
Now, I'm not 100% on your utilization here, but based off the initial issue I would use the Textupdate Event Handler like this:
private void comboBox1_TextUpdate(object sender, EventArgs e)
{
ClearCmboboxesOnFirstEmpty(comboBox_commodity.Text);
}
private void ClearCmboboxesOnFirstEmpty(string comboValue)
{
if(comboValue == "")
{
fillCommodityCombobox();
fillSourceCombobox();
fillUnitCombobox();
fillStatTypeCombobox();
}
}
I have listbox and its items are the selected dates from Calendar control in ASP.net. Now I need to filter them in foreach loop according to whether every single date is present database table or not. And the code for same I used is like as:
foreach (string item in ListBoxSelectedDates.Items)
{
string q = "select count(*) from event_calendar where _date='" + Convert.ToDateTime(item).ToString("yyyy-MM-dd") + "'";
MySqlCommand cmd = new MySqlCommand(q, conn);
conn.Open();
if ((long)(cmd.ExecuteScalar() ?? 0) == 0)
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Leave <br>";
i++;
}
else
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Holiday <br>";
i++;
}
conn.Close();
}
And getting error at first line of above code is:
Unable to cast object of type 'System.Web.UI.WebControls.ListItem' to
type 'System.String'.
I am not getting proper solution after continuously trying...
foreach (var _iterator in ListBoxSelectedDates.Items) // here "lstDate" is name of your list where you store all date.
{
string item = _iterator.ToString();
string q = "select count(*) from event_calendar where _date='" + Convert.ToDateTime(item).ToString("yyyy-MM-dd") + "'";
MySqlCommand cmd = new MySqlCommand(q, conn);
conn.Open();
if ((long)(cmd.ExecuteScalar() ?? 0) == 0)
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Leave <br>";
i++;
}
else
{
strBody += i + ". " + Convert.ToDateTime(item).ToString("dd-MMM-yyyy") + ", " + Convert.ToDateTime(item).DayOfWeek + " : Holiday <br>";
i++;
}
conn.Close();
}
You can use the ListItem.ToString() Method to convert the ListItem to a String.
foreach (var _iterator in ListBoxSelectedDates.Items)
{
string item = _iterator.ToString();
//The rest of your logic here
conn.Close();
}
If you want to access explicitly the value, you can have a look to the ListItem documentation, there you can see that there is a public property called Value so you can use instead:
string item = _iterator.Value;
so you get:
foreach (ListItem _iterator in ListBoxSelectedDates.Items)
{
string item = _iterator.Value;
//The rest of your logic here
conn.Close();
}
I was having problem when using "Date" property.
My class here:
public bool ChuyenDSChamCong()
{
try
{
DataTable dta = DSChamCong();
if (dta == null)
return false;
foreach (DataRow r in dta.Rows)
{
try
{
string sql = "delete FROM tk_dlchamcong where MD5(CONCAT(ma_chamcong,ma_nv, tg_check)) = md5('" + r["CardID"] + r["StaffID"] + r["TransDT"].ToString() + "')";
MYSQLDB.query(sql);
while (((DateTime)r["TransDT"]).Date == (DateTime.Today).Date)
{
string sql1 = "INSERT INTO tk_dlchamcong(ID,ma_chamcong, ma_nv, tg_check)values(md5('" + r["CardID"] + r["StaffID"] + r["TransDT"].ToString() + "'),'" + r["CardID"] + "', '" + r["StaffID"] + "', '" + r["TransDT"] + "')";
MYSQLDB.query(sql1);
}
}
catch {
}
}
return true;
}
catch { }
return false;
}
I cannot use Date() property, it accept with Date only. But when I debug it show like this and jump to catch error.
It cannot compare, r["TransDT"] is DateTime. Here is image show error.
Updated: r["TransDT"] is object{string} in database has values: 11/11/2015 18:03:11
I was format this with query like:
FORMAT(TransDT,'dd/MM/yyyy HH:mm:ss') as TransDT from Transact
Error when debug:
Animate screenshot gif
The value could be null(DBNull.Value), you coudl try to cast it to a DateTime? with the as-operator. When the cast fails you get a Nullable<DateTime> with HasValue=false:
DateTime? TransDT = r["TransDT"] as DateTime?;
if(TransDT.HasValue && TransDT.Value.Date == DateTime.Today)
{
// ...
}
You don't need a while, an if is sufficient since you have a single DataRow.
I am trying to build a web form that uses SQL queries to help populate various dropdowns and display results in gridviews, the issue i'm having at the moment is getting the user input to replace varibles in the SQL query.
My query is as follows:
SELECT TOP 50
'Select' AS 'Select',
id_ref AS 'Number',
created_date AS 'Date Created',
address 'Address',
category AS 'Category',
borough
FROM Events
WHERE location_address LIKE '%%'
AND borough #borcond
AND admin_ref #stacond
AND id_ref #Numcond
AND category #cat
AND created_date #startDate
AND created_date #endDate
AND address LIKE #Addresscond
ORDER BY id_todays_date DESC
My C# code is as follows:
public void SQLQueryv2(
string AddressSel,
string startDateSel,
string endDateSel,
string incidentSel,
string borsel,
string stasel,
string numsel)
{
//this is filled in really
SqlConnection Connection = new SqlConnection(
"Data Source=;Initial Catalog=;User=;Password=;");
string sqlquery = <<as above>>
try
{
SqlCommand Command = new SqlCommand(sqlquery, Connection);
Connection.Open();
if (borsel == "Select Borough")
{
Command.Parameters.AddWithValue("#borcond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#borcond","= " + "'" + borsel + "'");
}
if (stasel == "Select Town")
{
Command.Parameters.AddWithValue("#stacond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#borcond","= "+ "'" + borsel + "'");
}
if (startDateSel == "")
{
Command.Parameters.AddWithValue("#startDate", " = IS NOT NULL");
}
else
{
Command.Parameters.AddWithValue(
"#startDate",
">= CONVERT(datetime," + "'" + startDateSel + "'" + ",103)");
}
if (endDateSel == "")
{
Command.Parameters.AddWithValue("#endDate", " = IS NOT NULL");
}
else
{
Command.Parameters.AddWithValue(
"#endDate",
">= CONVERT(datetime," + "'" + endDateSel + "'" + ",103)");
}
if (incidentSel == "Select Category")
{
Command.Parameters.AddWithValue(
"#cat",
" in ('cat a','cat b','cat c')");
}
else
{
Command.Parameters.AddWithValue(
"#cat",
" AND category =" + "'" + incidentSel + "'");
}
if (AddressSel == "")
{
Command.Parameters.AddWithValue("#Addresscond", "%%");
}
else
{
Command.Parameters.AddWithValue("#Addresscond","%" + AddressSel + "%");
}
if (numsel == "")
{
Command.Parameters.AddWithValue("#Numcond", " = IS NOT NULL ");
}
else
{
Command.Parameters.AddWithValue("#Numcond", "= " + "'" + numsel + "'");
}
//use adapter to populate dataset...
SqlDataAdapter DataAdapter = new SqlDataAdapter(sqlquery, Connection);
DataTable DataTable = new DataTable();
DataAdapter.SelectCommand = Command;
DataAdapter.Fill(DataTable);
//then bind dataset to the gridview
GridView1.AutoGenerateColumns = true;
GridView1.DataSource = DataTable;
GridView1.DataBind();
lblResults.Visible = true;
lblResults.ForeColor = System.Drawing.Color.Green;
lblResults.Text = "Your search has returned "
+ Dataset.Tables[0].Select(
"'Incident Number' IS NOT NULL").Length.ToString()
+ " records.";
}
catch (Exception err)
{
lblResults.Visible = true;
lblResults.ForeColor = System.Drawing.Color.Red;
lblResults.Text =
"An error has occurred loading data into the table view. ";
lblResults.Text += err.Message;
}
}
When run, the Gridview doesn't populate and the query (when investigated) it still has the variables and not the 'is nulls' or user inputs.
I think its something to so with the IF statements but i'm entirely sure. I think i just need another pair of eyes on this, any help would be appreciated.
Bit more info:
If i take out the sqlCommand bits it works perfectly with the IF statements, i'm trying to stop people from using malicious SQL queries.
This really isn't the correct way to use parameters. You should only assign values to them, not add comparison operators. Here's an example of how to "fix" your query for the #borcond parameter
...
AND ((#borcond = 'Select Borough' AND borough IS NOT NULL)
OR borough = #borcond)
...
Note: you don't need the equal sign with IS NOT NULL
And replace the if-else with
Command.Parameters.AddWithValue("#borcond", borsel);
You'll need to do similar changes for all of your parameters. The trick here is to basically move your if-else logic from the code into the sql query.
Additionally I don't think you need the location_address LIKE '%%' in your query as that just matches everything.
What juhar said. You've got the wrong idea about parameters. They're parameters and not text substitution. Here's an example of a valid query:
Select firstname, lastname from contacts
where ssn = #ssn
And in your code you'd say
Command.parameters.AddWithValue("#ssn","123-45-6789")
First of all, please help me out! I can not take this anymore. I could not find where the error is located. Here is my problem:
I'm trying to update a row via c# winform application. The update query generated from the application is formatted correctly. I tested it in the sql server environment, it worked well. When i run it from the application i get 0 rows updated.
Here is the snippet that generates the update statement using reflection - don't try to figure it out. Carry on reading after the code portion:
public void Update(int cusID)
{
SqlCommand objSqlCommand = new SqlCommand();
Customer cust = new Customer();
string SQL = null;
try
{
if ((cusID != 0))
{
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
}
else
{
break;
}
}
}
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
DAL.ExecuteSQL(objSqlCommand);
}
else
{
//AppEventLog.AddWarning("Primary Key is not provided for Update.")
}
}
catch (Exception ex)
{
//AppEventLog.AddError(ex.Message.ToString)
}
}
This part below:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL + " WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " + "'" + "#phNum" + "'";
generates dml:
UPDATE CustomerPhone SET PhoneTypeID = #PhoneTypeID, PhoneNumber = #PhoneNumber WHERE CustomerID = #cusID AND PhoneNumber = '#phNum'
#PhoneTypeID and #PhoneNumber are gotten from two properties. We assigned the value to these properties in the presentation layer from the user input text box. The portion below where fetches the values:
objSqlCommand.Parameters.AddWithValue("#" + PropertyItem.Name.ToString(), PropertyItem.GetValue(this, null));
The code below fills the values of WHERE:
objSqlCommand.Parameters.AddWithValue("#cusID", cusID);
objSqlCommand.Parameters.AddWithValue("#phNum", this.PhoneNumber);
The final code should look as:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = '911';
Phone type id is 7 - user value that is taken from text box
Phone number is 999444 - user value that is taken from text box
The above final update statement works on the sql environment, but when running
via the application, the execute non query runs ok and gets 0 rows updated! I wonder why?
This is the problem:
AND PhoneNumber = '#phNum'
That's looking for a phone number which is exactly the text '#phNum' - it's not using a parameter called phNum. You want
AND PhoneNumber = #phNum
You're also breaking up your string literals for no obvious reason. This statement:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " + cust.PKName + " = #cusID AND PhoneNumber = " +
"'" + "#phNum" + "'";
would be more easily readable as:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = '#phNum'";
Obviously you want to drop the single quotes from it, to make it just:
objSqlCommand.CommandText = "UPDATE " + this.TableName + " SET " + SQL +
" WHERE " cust.PKName + " = #cusID AND PhoneNumber = #phNum";
A little refactoring wouldn't go amiss, either. This loop:
foreach (PropertyInfo PropertyItem in this.GetType().GetProperties())
{
if (!(PropertyItem.Name.ToString() == cust.PKName))
{
if (PropertyItem.Name.ToString() != "TableName")
{
if (SQL == null)
{
SQL = PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
else
{
SQL = SQL + ", " + PropertyItem.Name.ToString() + " = #" + PropertyItem.Name.ToString();
}
}
else
{
break;
}
}
}
would be more simpler and more readable like this:
StringBuilder sqlBuilder = new StringBuilder();
foreach (PropertyInfo property in this.GetType().GetProperties())
{
string name = property.Name;
// I believe you had a bug before - the properties being updated
// would depend on the ordering of the properties - if it
// ran into "TableName" first, it would exit early!
// I *suspect* this is what you want
if (name != cust.PKName && name != "TableName")
{
sqlBuilder.AppendFormat("{0} = #{0}, ", name);
}
}
// Remove the trailing ", "
if (sqlBuilder.Length > 0)
{
sqlBuilder.Length -= 2;
}
You can do something similar with the final loop too.
Is PhoneNumber a string, or an integer?
I see you're SETting as a integer, but checking in the WHERE as a literal. Could this not be the problem?
If it's an integer, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = 999444
WHERE CustomerID = 500 AND PhoneNumber = 911;
If it's a string, try:
UPDATE CustomerPhone
SET PhoneTypeID = 7, PhoneNumber = '999444'
WHERE CustomerID = 500 AND PhoneNumber = '911';