There are 5 goals and 5 employees. Each goal can be assigned to any number of these 5 employees. So I have 5 CheckBoxLists for each of the goals, each CheckBoxList having the names of these 5 employees as items.
I want to retrieve from the database which employees have been assigned which goals. I have the following piece of code:
List<CheckBoxList> checkboxlists = new List<CheckBoxList>();
checkboxlists.Add(CheckBoxList1);
checkboxlists.Add(CheckBoxList2);
checkboxlists.Add(CheckBoxList3);
checkboxlists.Add(CheckBoxList4);
checkboxlists.Add(CheckBoxList5);
for (int z = 1; z <= checkboxlists.Count; z++)
{
SqlCommand check = new SqlCommand("SELECT ISGoal1, ISGoal2,ISGoal3, ISGoal4,ISGoal5 FROM PRM2011_EMPLOYEE_GOAL WHERE EmployeeID = '" + employeeid[z - 1] + "'", con);
SqlDataReader y = check.ExecuteReader();
y.Read();
for (int j = 1; j <= 5; j++)
{
if (null != y && y.HasRows)
{
string yes_or_no = y["ISGoal" + j].ToString().Trim();
if (yes_or_no == "Yes")
{
checkboxlists[j-1].Items[z-1].Selected = true;
}
//else checkboxlists[j - 1].Items[z - 1].Selected = false;
}
}
y.Close();
}
My problem is that even if I select one goal for an employee, all the checkboxes corresponding to that particular employee get selected. Why is this happening?
Correspondingly, if I comment out the else portion in the code posted, and if any of the goals are not selected, then all the checkboxes corresponding to that employee goes unselected. Please help.
A few thoughts:
Have your for loops go from 0 to less than checkboxlists.Count and from 0 to less than 5. That way you can avoid having to deal with all the subtractions everywhere.
On the line checkboxlists[j-1].Items[z-1].Selected = true, shouldn't it be checkboxlists[z-1].Items[j-1].Selected = true since I am assuming you are using z to iterate over your CheckBoxLists.
Its late here, so my brain may be a bit fuzzy, but it seems that #2 could be your issue. Give those thoughts a shot and I will follow up with you if you are still having issues.
You have many issues in your code I'll tell you the main problem and then I'll list the other flaws of your code.
What's causing this is:
the existence of the method y.Read(); out side of the for loop.
since the function of Read(); is to read the next row in the database. so basically your code reads the first value, Let's assume the value will be "Yes" so it will cause the ListBox to check the employee and instead of calling the y.Read(); again so it moves to the next row it DOES NOT! .. so the value is kept "Yes" and hense all the CheckBoxes in the List will be checked.
The Solution:
It's as simple as just moving the y.Read(); from out side the loop into it.
Like this:
List<CheckBoxList> checkboxlists = new List<CheckBoxList>();
checkboxlists.Add(CheckBoxList1);
checkboxlists.Add(CheckBoxList2);
checkboxlists.Add(CheckBoxList3);
checkboxlists.Add(CheckBoxList4);
checkboxlists.Add(CheckBoxList5);
for (int z = 1; z <= checkboxlists.Count; z++)
{
SqlCommand check = new SqlCommand("SELECT ISGoal1, ISGoal2,ISGoal3, ISGoal4,ISGoal5 FROM PRM2011_EMPLOYEE_GOAL WHERE EmployeeID = '" + employeeid[z - 1] + "'", con);
SqlDataReader y = check.ExecuteReader();
for (int j = 1; j <= 5; j++)
{
y.Read();
if (null != y && y.HasRows)
{
string yes_or_no = y["ISGoal" + j].ToString().Trim();
if (yes_or_no == "Yes")
{
checkboxlists[j-1].Items[z-1].Selected = true;
}
//else checkboxlists[j - 1].Items[z - 1].Selected = false;
}
}
y.Close();
}
Extra Notes on your code
First of all
You need to edit your SqlCommand to use SqlParameters
SqlCommand check = new SqlCommand("SELECT ISGoal1, ISGoal2,ISGoal3, ISGoal4,ISGoal5 FROM PRM2011_EMPLOYEE_GOAL WHERE EmployeeID = #EmpID", con);
check.Parameters.AddWithValue("#ImpID", employeeid[z - 1]);
Second
If you are trying to build a real application then this is a very bad practice. Even if you are not building this application for real I don't think this is the way to practice.
for (int j = 1; j <= 5; j++)
your Loop should look like this:
for (int j = 1; j <= checkboxlists.Count; j++)
Third
Using a string to represent a Yes/No value is a also a bad practice .. You should use for all your ISGoal columns database, the DataType BIT. and consequently you'll change the local variable's DateType in your C# code from string to bool.
Fourth
checkboxlists[j-1].Items[z-1].Selected = true;
You should switch as Ryan said, because z denotes to the CheckBoxLists and j denotes to the items of a given CheckBoxList
so it could be like this:
checkboxlists[z-1].Items[j-1].Selected = true;
N.B: I wasn't paying attention at first I thougth [z-1] is some kind of LINQ expression :D!! .. It's my fault but I mean I used to do this when I first started programming and I still couldn't recognize it .. It's not the best practice I think! .. my advice respect the used Zero-Based numbering.
Finally
You don't have to check everytime if y.Read(); is null or not. So I think this piece of code would make more sense and also hard coding the condition of the loop is a very bad practice, so we'll use a while loop and add local variable of type int, then we'll increment it within our loop code so you could use it to access the CheckBoxList items
int j = 1;
while (y.Read())
{
string yes_or_no = y["ISGoal" + j].ToString().Trim();
if (yes_or_no == "Yes")
{
checkboxlists[j-1].Items[z-1].Selected = true;
//use our counter "j" here
}
//else checkboxlists[j - 1].Items[z - 1].Selected = false;
//use our counter "j" here
j++;
}
..Good Luck ;)
Related
I have gridview that contains check boxes in one of the columns, then there is a "Select ALl" button which when clicked has to check top 100 CBs on the list, the client specifically stated they do not want pagination, it much easier to do this with pagination and display only 100 records per page then when the select all button is clicked everything on the given page gets selected however this is not what the client wants
Here is my code:
foreach (GridViewRow row in dgridTransactions.Rows)
{
for (int x = 0; x <=100;x++ )
{
var oneTransaction = (CheckBox)row.FindControl("chkAssigned");
oneTransaction.Checked = true;
}
}
If you want to run first hundred rows you only need this loop
for(int x = 0; x < 100; x++)
{
GridViewRow row = dgridTransactions.Rows[x];
// then manage row properties
CheckBox cb = (CheckBox)row.FindControl("chkAssigned");
cb.Checked = true;
}
using RowIndex you can keep track of row number.
foreach (GridViewRow row in dgridTransactions.Rows)
{
if(row.RowIndex<100 )
{
var oneTransaction = (CheckBox)row.FindControl("chkAssigned");
oneTransaction.Checked = true;
}
else
break;
}
There is issue in your code
You can use the below code
int x=0;
foreach (GridViewRow row in dgridTransactions.Rows)
{
if(x<100 )
{
var oneTransaction = (CheckBox)row.FindControl("chkAssigned");
oneTransaction.Checked = true;
}
else
break;
x++;
}
The foreach (GridViewRow row in dgridTransactions.Rows) loop runs for each row in your grid.
and in that you are using for (int x = 0; x <=100;x++ ){ which runs 100 times for every row.
You can use jquery or javascript for this Here is a JSFiddle which can help you
How about:
foreach (GridViewRow row in dgridTransactions.Rows.Cast<GridViewRow>().Take(100)) {
CheckBox cb = row.FindControl("chkAssigned") as CheckBox;
if (cb != null)
cb.Checked = true;
}
This will give the first items up to 100, so if you only have 90, it will give 90.
The diferent way of casting will also give you an additional security measure in case it fails to find the control. A direct cast will just throw an exception, which is always heavier then checking if the castes object is not null...
If you dont care about the cast verification, you can just inline everything into this:
dgridTransactions.Rows.Cast<GridViewRow>().Take(100).ToList().ForEach(x => ((CheckBox)x.FindControl()).Checked = true);
public int AuthenticatedUserAge(String User_name)
{
string sql = "SELECT UserName,Age FROM tblDataProg WHERE (UserName ='" + User_name + "')";
ds = GetDataSet(sql);
int help = int.Parse(ds.Tables[0].Rows[0]["Age"].ToString());
return help;
}
I can't figure why this line doesn't convert the age to type int and return a value:
int help = int.Parse(ds.Tables[0].Rows[0]["Age"].ToString());
Completely offtopic to the question, but I think it's worth mentioning. Please don't create your SQL statements by concatenating strings. This creates SQL Injection attack possibility. Instead consider SqlParameter class and compose your WHERE predicates using such parameters.
Here you get nice example (look especially at convenient AddWithValue method).
Thanks!
Test your assumptions more. You are assuming GetDataSet is returning a row but it possibly isn't: -
int help = 0;
if (ds.Tables[0].Rows.Count == 0)
{
throw new ApplicationException("no rows were returned, here is an error to deal with");
}
else if (ds.Tables[0].Rows[0]["Age"] == System.DbNull.Value)
{
throw new ApplicationException("a row was found but Age is null, here is an error to deal with");
}
else
{
help = int.Parse(ds.Tables[0].Rows[0]["Age"].ToString());
}
try
int help;
int.TryParse(Convert.ToString(ds.Tables[0].Rows[0]["Age"]),out help);
and see the code in debug mode
I have this code
using (var contents = connection.CreateCommand())
{
contents.CommandText = "SELECT [subject],[note] FROM tasks";
var r = contents.ExecuteReader();
int zaehler = 0;
int zielzahl = 5;
while (r.Read())
{
if (zaehler == zielzahl)
{
//access r["subject"].ToString()
}
zaehler++;
}
}
I want to make it faster by accessing zielzahl directly like r[zielzahl] instead of iterating through all entries. But
r[zielzahl]["subject"]
does not work aswell as
r["subject"][zielzahl]
How do I access the column subject of result number zielzahl?
To get only the sixth record, use the OFFSET clause:
SELECT subject, note
FROM tasks
LIMIT 1 OFFSET 5
Please note that the order of returned records is not guaranteed unless you use the ORDER BY clause.
Im writing SSAS MDX queries involving more than 2 axis' to retrieve a value. Using ADOMD.NET, I can get the returned cellset and determine the value by using
lblTotalGrossSales.Text = CellSet.Cells(0).Value
Is there a way I can get the CellSet's Cell(0) Value in my MDX query, instead of relying on the data returning to ADOMD.NET?
thanks!
Edit 1: - Based on Daryl's comment, here's some elaboration on what Im doing. My current query is using several axis', which is:
SELECT {[Term Date].[Date Calcs].[MTD]} ON 0,
{[Sale Date].[YQMD].[DAY].&[20121115]} ON 1,
{[Customer].[ID].[All].[A612Q4-35]} ON 2,
{[Measures].[Loss]} ON 3
FROM OUR_CUBE
If I run that query in Management Studio, I am told Results cannot be displayed for cellsets with more than two axes - which makes sense since.. you know.. there's more than 2 axes. However, if I use ADOMD.NET to run this query in-line, and read the returning value into an ADOMD.NET cellset, I can check the value at cell "0", giving me my value... which as I understand it (im a total noob at cubes) is the value sitting where all these values intersect.
So to answer your question Daryl, what I'd love to have is the ability to have the value here returned to me, not have to read in a cell set into the calling application. Why you may ask? Well.. ultimately I'd love to have one query that performs several multi-axis queries to return the values. Again.. Im VERY new to cubes and MDX, so it's possible Im going at this all wrong (Im a .NET developer by trade).
Simplify your query to return two axis;
SELECT {[Measures].[Loss]} ON 0, {[Term Date].[Date Calcs].[MTD] * [Sale Date].[YQMD].[DAY].&[20121115] * [Customer].[ID].[All].[A612Q4-35]} ON 1 FROM OUR_CUBE
and then try the following to access the cellset;
string connectionString = "Data Source=localhost;Catalog=AdventureWorksDW2012";
//Create a new string builder to store the results
System.Text.StringBuilder result = new System.Text.StringBuilder();
AdomdConnection conn = new AdomdConnection(connectionString);
//Connect to the local serverusing (AdomdConnection conn = new AdomdConnection("Data Source=localhost;"))
{
conn.Open();
//Create a command, using this connection
AdomdCommand cmd = conn.CreateCommand();
cmd.CommandText = #"SELECT { [Measures].[Unit Price] } ON COLUMNS , {[Product].[Color].[Color].MEMBERS-[Product].[Color].[]} * [Product].[Model Name].[Model Name]ON ROWS FROM [Adventure Works] ;";
//Execute the query, returning a cellset
CellSet cs = cmd.ExecuteCellSet();
//Output the column captions from the first axis//Note that this procedure assumes a single member exists per column.
result.Append("\t\t\t");
TupleCollection tuplesOnColumns = cs.Axes[0].Set.Tuples;
foreach (Microsoft.AnalysisServices.AdomdClient.Tuple column in tuplesOnColumns)
{
result.Append(column.Members[0].Caption + "\t");
}
result.AppendLine();
//Output the row captions from the second axis and cell data//Note that this procedure assumes a two-dimensional cellset
TupleCollection tuplesOnRows = cs.Axes[1].Set.Tuples;
for (int row = 0; row < tuplesOnRows.Count; row++)
{
for (int members = 0; members < tuplesOnRows[row].Members.Count; members++ )
{
result.Append(tuplesOnRows[row].Members[members].Caption + "\t");
}
for (int col = 0; col < tuplesOnColumns.Count; col++)
{
result.Append(cs.Cells[col, row].FormattedValue + "\t");
}
result.AppendLine();
}
conn.Close();
TextBox1.Text = result.ToString();
} // using connection
Source : Retrieving Data Using the CellSet
This is fine upto select on columns and on Rows. It will be helpful analyze how to traverse sub select queries from main query.
I've got a JS array which is writing to a text file on the server using StreamWriter. This is the line that does it:
sw.WriteLine(Request.Form["seatsArray"]);
At the moment one line is being written out with the entire contents of the array on it. I want a new line to be written after every 5 commas. Example array:
BN,ST,A1,303,601,BN,ST,A2,303,621,BN,WC,A3,303,641,
Should output:
BN,ST,A1,303,601,
BN,ST,A2,303,621,
BN,WC,A3,303,641,
I know I could use a string replace but I only know how to make this output a new line after every comma, and not after a specified amount of commas.
How can I get this to happen?
Thanks!
Well, here's the simplest answer I can think of:
string[] bits = Request.Form["seatsArray"].Split(',');
for (int i = 0; i < bits.Length; i++)
{
sw.Write(bits[i]);
sw.Write(",");
if (i % 5 == 4)
{
sw.WriteLine();
}
}
It's not terribly elegant, but it'll get the job done, I believe.
You may want this afterwards to finish off the current line, if necessary:
if (bits[i].Length % 5 != 0)
{
sw.WriteLine();
}
I'm sure there are cleverer ways... but this is simple.
One question: are the values always three characters long? Because if so, you're basically just breaking the string up every 20 characters...
Something like:
var input = "BN,ST,A1,303,601,BN,ST,A2,303,621,BN,WC,A3,303,641,";
var splitted = input.Split(',');
var cols = 5;
var rows = splitted.Length / cols;
var arr = new string[rows, cols];
for (int row = 0; row < rows; row++)
for (int col = 0; col < cols; col++)
arr[row, col] = splitted[row * cols + col];
I will try find a more elegant solution. Properly with some functional-style over it.
Update: Just find out it is not actually what you needs. With this you get a 2D array with 3 rows and 5 columns.
This however will give you 3 lines. They do not have a ending ','. Do you want that? Do you always want to print it out? Or do you want to have access to the different lines?:
var splitted = input.Split(new [] { ','}, StringSplitOptions.RemoveEmptyEntries);
var lines = from item in splitted.Select((part, i) => new { part, i })
group item by item.i / 5 into g
select string.Join(",", g.Select(a => a.part));
Or by this rather large code. But I have often needed a "Chunk" method so it may be reusable. I do not know whether there is a build-in "Chunk" method - couldn't find it.
public static class LinqExtensions
{
public static IEnumerable<IList<T>> Chunks<T>(this IEnumerable<T> xs, int size)
{
int i = 0;
var curr = new List<T>();
foreach (var x in xs)
{
curr.Add(x);
if (++i % size == 0)
{
yield return curr;
curr = new List<T>();
}
}
}
}
Usage:
var lines = input.Split(',').Chunks(5).Select(list => string.Join(",", list));