my sql returns only single value - c#

I have
staff table
staff_Id
staff_Accesscode values (access123,code123,staff12)....
i have done like this for getting all values in staff_accesscode
DataTable dt2 = null;
string sql = #"SELECT staff_AccessCode FROM staff";
dt2 = xxxxxx.GetData(sql, gBaseUrl);
if (dt2 != null && dt2.Rows.Count > 0)
{
accessname = dt2.Rows[0]["staff_AccessCode"].ToString();
}
but the problem is it returns only last value stored in staff_Accesscode, I mean it returns only this value (staff12)
now i want to get the all values stored in staff_Accesscode field and further i want to check this value with the txtbox.text

You're only accessing the first row in the line accessname = dt2.Rows[0]...; you need to loop through all of the available rows in the collection.

You are accessing the first row (with index 0) only.
You might iterate through the complete result set:
for ( int i = 0; dt2 != null && i < dt2.Rows.Count; ++i )
{
String tmp = dt2.Rows[ i ]["staff_AccessCode"].ToString();
if ( tmp.Equals( what_ever_variable_or_constant /* e.g., txtbox.Text */ ) )
{
accessname = tmp;
//break; ?
}
}

Related

Is there a way to get the last non-null values of each column in a C# DataTable and display them as a single row?

I want to take the last non-null values of each column in a DataTable and create a single row with them.
Sample code:
DataTable temp; // temp is the DataTable shown on the left side in the "Current Result" section
DataTable temp2; // stores the newly create DataTable row
foreach(DataRow row in temp.Rows){
object[] Item = new object[] {};
foreach(DataColumn col in temp.Columns){
if (row[col] != null || row[col] != DBNull.Value || !String.IsNullOrWhiteSpace(row[col].ToString()))
{
Array.Resize(ref Item, Item.Length + 1);
Item[Item.Length - 1] = row[col];
}
}
temp2.Rows.Add(Item);
}
My code currently copies all of the cells from one DataTable to another, including the cells that don't have any values stored in it.
Current Result:
In the photo below, I blacked out all the cells except of the last non-values of each column. I want the shown values to be stored and displayed as a single row.
Desired Result:
I don't know if the problem is solved. Her are my suggestion to solve the problem. I would go from the last row up to the first, because the task is to have the last value from each column and then the loop is may be erlier finish, as when you go from the top to the bottom of the table. But this I think also depends on the data in the table.
DataTable temp = yourTable; // the original table
DataTable temp2 = new DataTable();
object[] lastNonNullValues = new object[temp.Columns.Count];
// Index of the last row.
int lastRow = temp.Rows.Count - 1;
// Get from the last row to the first
for (int i = lastRow; i >= 0; i--)
{
// Don't know if necessary but if all columns has an value -> finish.
if (lastNonNullValues.All(x => x != null)) break;
DataRow row = temp.Rows[i];
for (int j = 0; j < temp.Columns.Count; j++)
{
// Continue if some value was written
if (lastNonNullValues[j] != null) continue;
// None of this condition should be true, thas why should change from || to &&
if (row[j] != null && row[j] != DBNull.Value && !string.IsNullOrWhiteSpace(row[j].ToString()))
{
lastNonNullValues[j] = row[j];
}
}
}
temp2.Rows.Add(lastNonNullValues);
Notice:
The solution of Rufus L should also be work when change the if statement from or to and-conjunction.
It seems to me that you're just looking to add a single row to the temp2 table, which has the last non-null value for each column. If that's the case, then you can initialize the object[] with the Columns.Count size, and we can loop through the columns using the column index, which allows us to assign a new value to an existing column when we find a non-null value for it in the current row:
DataTable temp = new DataTable();
DataTable temp2 = temp.Clone();
// A single row of data that is 'Columns.Count' long
object[] lastNonNullValues = new object[temp.Columns.Count];
foreach (DataRow row in temp.Rows)
{
// Loop through columns using the column index rather than a foreach
for (int i = 0; i < temp.Columns.Count; i++)
{
var col = temp.Columns[i];
if (row[col] != null || row[col] != DBNull.Value ||
!string.IsNullOrWhiteSpace(row[col].ToString()))
{
// Now we just assign the value at the index for this column
lastNonNullValues[i] = row[col];
}
}
}
// Add our single row to the results table
temp2.Rows.Add(lastNonNullValues);

How to conditional sum from gridview or from sql database in C#

I have a situation that I need to calculate total sum (from a SQL database table or from a gridview) column "ptarcvGV" if the column "PtR" cells equal to (combobox) AcPtPtrDd.selectedItem. In the following code I am getting total of all column cells in Label AcPTRcvdLbl.Text but I want to get conditional total as per selection of combobox.text.(combobox having unique id numbers only , column "ptarcvGV" having partial Payment received, column "PtR" having repeated id numbers)
code:
private void AcPtTrekBtn_Click(object sender, EventArgs e)
{
int sum = 0;
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
if (dataGridView1.Rows[i].Cells["ptarcvGV"].Value != null)
{
sum += Convert.ToInt32(dataGridView1.Rows[i].Cells["ptarcvGV"].Value.ToString());
AcPTRcvdLbl.Text = Convert.ToString(sum);
}
}
}
One more thing that I did following line of code in SQL and worked fine but I am unable to use it in my c# form.
line of code:
Select SUM (pta_rcv) FROM PtAccounts where (pta_ptr) = 13 --13 is id in pta_ptr
Thanks Karan for your idea it worked now with little change as follows:
if (dataGridView1.Rows[i].Cells["ptaptrGV"].Value.ToString() == AcPtPtrDd.Text &&
dataGridView1.Rows[i].Cells["ptarcvGV"].Value != null)
I added ToString() and also changed at AcPtPtrDd.Text insted of AcPtPtrDd.SelectedItem
All done well
decimal value = decimal.Parse(dt.Compute("SUM(columnName)","filterColumn='key'").ToString());
Update your if condition as below.
if (dataGridView1.Rows[i].Cells["ptarcvGV"].Value != null &&
dataGridView1.Rows[i].Cells["PtR"].Value == AcPtPtrDd.selectedItem)
{
//Your code
}
To compare string case insensitive way update conditions as follow.
if (dataGridView1.Rows[i].Cells["ptarcvGV"].Value != null &&
string.Equals(dataGridView1.Rows[i].Cells["PtR"].Value.ToString(), AcPtPtrDd.SelectedItem.ToString(), StringComparison.OrdinalIgnoreCase))
{
//Your code
}
double Sum_1 = 0;
double Sum_2 = 0;
foreach (GridViewRow row in gvComps.Rows)
{
// sum all -- no condition
Sum_1 += Convert.ToDouble(row.Cells[3].Text);
// sum with condition
if (row.Cells[7].Text=="yes")
Sum_2 += Convert.ToDouble(row.Cells[3].Text);
}
txtSum_1.Text = Sum_1.ToString();
txtSum_2.Text = Sum_2.ToString();

Extract the sum of two things from datatable

I have a table in a SQL Server database with many columns but the important columns are LoggedState and InteractionType.
I need to find the number of break agents and the number of idle agents.
What I have tried
SqlCommand GraphCmd = new SqlCommand("getAgentStatues", Graphsqlcon);
SqlParameter tdate = new SqlParameter();
GraphCmd.CommandType = CommandType.StoredProcedure; ;
SqlDataAdapter DAGraph = new SqlDataAdapter(GraphCmd);
DataSet DSGraph = new DataSet();
DSGraph.Clear();
DAGraph.Fill(DSGraph);
DataTable DTgraph = new DataTable();
DTgraph = DSGraph.Tables[0];
int numberOfBreakAgents = 0;
int numberOfIdelAgents = 0;
foreach (DataRow row in DTgraph.Rows)
{
String LoggedState = row["LoggedState"].ToString().Trim().ToLower();
String InteractionType = row["InteractionType"].ToString();
if (LoggedState == "break")
{
numberOfBreakAgents++;
}
else if ((LoggedState == "activo") && (row["InteractionType"] == DBNull.Value))
{
numberOfIdelAgents++;
}
}
it works perfectly, but I am asking if there is a way (like grouping) to avoid the foreach statement
You could use the Group function from Linq:
var loggedStateGroups = dt.AsEnumerable().GroupBy(d => d["LoggedState"].ToString(), (group, row) => new
{
LoggedState = group,
AllCount = row.Count(),
NullCount = row.Where(r => r["InteractionType"] == DBNull.Value).Count()
});
That will group by the LoggedState with a count for each matching row (AllCount) and a count for rows where the InteractionType is DBNull.Value (NullCount).
We can then select the counts we are after by doing:
int numberOfBreakAgents = loggedStateGroups.Where(y => y.LoggedState == "break").First().AllCount;
int numberOfIdelAgents = loggedStateGroups.Where(y => y.LoggedState == "activo").First().NullCount;
Note I'm only using First assuming you will always have results. If you won't always have results you should use FirstOrDefault and perform a null check.
You could filter before using the Group by adding the following Where depending on your data.
.Where(r => r["LoggedState"].ToString() == "break" || r["LoggedState"].ToString() == "activo")
I've tested this with the following setup:
DataTable dt = new DataTable();
dt.Columns.Add("LoggedState");
dt.Columns.Add("InteractionType");
dt.Rows.Add("break", "inter1");
dt.Rows.Add("activo", DBNull.Value);
dt.Rows.Add("break", "inter1");
dt.Rows.Add("break", "inter2");
dt.Rows.Add("activo", "inter2");
And I get 3 and 1 for the numberOfBreakAgents and numberOfIdelAgents respectively.
Edit for using FirstOrDefault:
If you'd like to perform the null check as mentioned above you can replace the two int declaration lines above with:
var breakAgents = loggedStateGroups.Where(y => y.LoggedState == "break").FirstOrDefault();
var idelAgents = loggedStateGroups.Where(y => y.LoggedState == "activo").FirstOrDefault();
int numberOfBreakAgents = breakAgents != null ? breakAgents.AllCount : 0;
int numberOfIdelAgents = idelAgents != null ? idelAgents.NullCount : 0;
This is taking the first group that has the LoggedState of "break" or null if there isn't one. It then assigns numberOfBreakAgents the AllCount property if the group is not null or 0 if it is.
A similar thing is done for numberOfIdelAgents except we filter for the "activo" group and use the NullCount property as we aren't interested in all rows we are only interested in those where the InteractionType was DBNull.Value which we've captured in the NullCount property.
The null check is necessary if the result set will ever contain zero rows with the LoggedState of "activo" or zero rows with the LoggedState of "break". In that instance the .First() will return null and accessing AllCount or NullCount from that will result in a "Sequence contains no elements" exception.
Using the following DataTable definition will highlight the difference as it causes an exception for numberOfBreakAgents using First() but correctly returns 0 when using FirstOrDefault.
DataTable dt = new DataTable();
dt.Columns.Add("LoggedState");
dt.Columns.Add("InteractionType");
dt.Rows.Add("activo", "inter1");
dt.Rows.Add("activo", DBNull.Value);
dt.Rows.Add("activo", "inter1");
dt.Rows.Add("activo", "inter2");
dt.Rows.Add("activo", "inter2");
Could you not do
var breakAgents = from row in DTgraph.AsEnumerable()
where row["LoggedState"].ToString().Trim().ToLower() == "break"
select row;
var breakAgentsCount = breakAgents.Count();
and
var idleAgents = from row in DTgraph.AsEnumerable()
where row["LoggedState"].ToString().Trim().ToLower() == "activo"
&& row["InteractionType"] == DBNull.Value
select row;
var idleAgentsCount = idleAgents.Count();
Using the Count-function that LINQ provides us, the following solution should work:
// Cast the rows to a collection of DataRows.
IEnumerable<DataRow> collection = DTgraph.Rows.Cast<DataRow>();
// Get the number of Break Agents.
int numberOfBreakAgents = collection.Count(row => row["LoggedState"].ToString().Trim().ToLower() == "break");
// Get the number of Idel Agents.
int numberOfIdelAgents = collection.Count(row => row["LoggedState"].ToString().Trim().ToLower() == "activo" && row["InteractionType"] == DBNull.Value);
The cast is used to allow the use of LINQ on the DataRow-collection.
Another option would be to cast the DataRow-collection to a List of type DataRow. Then using a ForEach (also LINQ), to determine the agent-type:
List<DataRow> collection = DTgraph.Rows.Cast<DataRow>().ToList();
collection.ForEach(row =>
{
if (row["LoggedState"].ToString().Trim().ToLower() == "break")
numberOfBreakAgents++;
else if (row["LoggedState"].ToString().Trim().ToLower() == "activo" && row["InteractionType"] == DBNull.Value)
numberOfIdelAgents++;
});
Above example is very much the same to your example, but written a bit shorter and without the use of two strings (LoggedState and InteractionType).
You can execute sql query like this:
select
sum(case when LoggedState = "break" then 1 else 0 end) break_count,
sum(case when LoggedState = "activo" and InteractionType is null then 1 else 0 end) active_count
from table_name

check if a value exists in DataRow array

In my application i am filtering a datatable using a filter expression and am getting a DataRow which matches the condition.Now i want to check if the value of particular column exists in any row of DataRow array.
Code:
string FilterCond1 = "id=" + getId;
DataRow[] myrow = DataTable.Select(FilterCond1);
if (myrow.Length > 0)
{
//check for size=28 in DataRow[]
}
else
{
}
I have column size in the datatable DataTable and i want to check if any row of the DataRow array has a value 28 in the column size.How can i go about it?
Try this
string FilterCond1 = "id=" + getId;
DataRow[] myrow = DataTable.Select(FilterCond1);
if (myrow.Length > 0)
{
for(int i = 0; i < myrow.Length; i ++)
{
if(myrow[i]["size"].ToString() == "28")
{
// YOUR CODE HERE
}
}
}
else
{
}
EDIT
Just add the condition to your filter.
string FilterCond1 = "id=" + getId + " AND size=28";
Then you don't need the if(myrow[i]["size"].ToString() == "28") as you know the rows in the array are the one you want.
You can use column collection to access particular column value within row.
if(myrow[rowIndex]["ColoumnName"].ToString() == "somevalue")
Where row index could from zero to length-1
Edit based on comments, you can put multiple condition on column in select, check it here, and may not need to iterate.
string FilterCond1 = "id=" + getId + " AND size = " + 28;
DataRow[] myrow = dt.Select(FilterCond1);
To iterate through rows collection
for(int i=0; i < myrow.Length; i++)
{
if(myrow[i]["size"].ToString() == "28")
{
//your code
}
}
First you should aiterate through all rows using foreach then use the below code..
if(myrow[row]["size"] == 28)
or
int ColIndex = 3; // replace 3 with ur co. index
if(myrow[row][ColIndex] == 28)

Update A Single cell within a row in datatable which contains multiple rows

How would i go about updating a single cell in a row so for example Row[0] i want to update the column "Value" with its current value +1. This is code i have which selects the single row but the Value updates with all the column "Value" data then +1
public void MetricChange()
{
DataTable dt = ds.Tables["MetricTable"];
int value = dt.AsEnumerable().Sum(r1 => r1.Field<int>("Value"));
if (Access.Checked)
{
ds.Tables["MetricTable"].Rows[0]["Value"] = value +1;
//ds.Tables["MetricTable"].Rows[1]["Value"] = value - 1;
Chart2.DataSource = ds.Tables["MetricTable"];
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
How would i just update the "Value" column within a single row???
Currently you are modifying only a single row, you need to do that for each row in the data table.
for(int i = 0; i < ds.Tables["MetricTable"].Rows.Count;i++)
ds.Tables["MetricTable"].Rows[i]["Value"] = value +1;
Its always better to check the dataset against null and table existence. Something like.
if(ds != null && ds.Tables.Count > 0 && ds.Tables["MetricTable"] != null)
This is how you do it :P
int val = Convert.ToInt32(ds.Tables["MetricTable"].Rows[0]["Value"]) + 1;
Then Update the row by this ds.Tables["MetricTable"].Rows[0][1] = val

Categories