Linq to DataTable not producing Distinct values - asp.net

I have a datatable which has been dynamically generated from FoxPro tables using a UNION Select statement. e.g.
SELECT * FROM x UNION SELECT * FROM y UNION SELECT * FROM Z ORDER By v_alue1
This produces a datatable with about 100 rows, each containing many fields, one of which is c_olor. From this datatable, I would like to select the distinct colors and then output in a dropdown.
I have a public class Color which just has one property which I can then use as the DataTextField and DataValueField for the dropdownlist
Public Class Color
Private _c_olor As String
Public Property c_olor() As String
Get
Return _c_olor
End Get
Set(ByVal value As String)
_c_olor = value
End Set
End Property
End Class
My linq statment is
Dim colorDs = (From o In dt.Rows Select Color = New With {.c_olor = o("c_olor").ToString().Trim(Nothing).ToLower()}).Distinct().ToList()
However this never results in the distinct colors.
I have searched and searched for what I am looking for, and this seems to be one of the methods to produce a distinct set of results, but this and the others do not work.
My reasoning behind getting the colors this way, is that I need to get various other distinct values from the same UNION SELECT datasource, so would just do one DB call, cache the results, and then just used this cached datasource to retrieve all my distinct values.

I'm not a VB expert but it seems like you're creating your colors first and then trying to find the distinct colors
In this case, you need to implement Equals on your color class
Dim colorDs = (From o In dt.Rows Select Color = New With {.c_olor = o("c_olor").ToString().Trim(Nothing).ToLower()}).Distinct().ToList()
Alternatively, you could find disctinct values first and then create color instances
Dim colorDs = (From o In dt.Rows Select o("c_olor").ToString().Trim(Nothing).ToLower()).Distinct().ToList()
Should produce the list of unique string colors

Related

How can I store the y value of a chart series in a label on my page?

I am curious how I can access the value of a YValueMember in a chart that I am populating through a database and display that value in a label. Basically I want to set a labels text equal to the y value of my chart.
I am populating my chart through a db query and setting the YValueMembers to the alias I use within my query
SELECT ( SELECT SUM(DealerNet) FROM Agreement WHERE VoidDate IS NULL
AND IssueDate BETWEEN #PFOM AND #date) AS Actual,
(SELECT SUM(Amount) FROM Sales
WHERE [Year] BETWEEN YEAR(#PFOM) AND YEAR(#date)
AND [Month] BETWEEN MONTH(#PFOM) AND MONTH(#date)) AS Projected
I then pass this query to a function I have to populate a DataTable called GetData() as seen in the call below.
GetData() Function:
Private Shared Function GetData(cmdSQL As SqlCommand, ByVal Optional strCon As String = "") As DataTable
If strCon = "" Then
strCon = ConfigurationManager.ConnectionStrings("WarrantyConnectionString").ToString
End If
Dim rstData As New DataTable
Using conn As New SqlConnection(strCon)
Using (cmdSQL)
cmdSQL.Connection = conn
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
Chart Code:
Dim cmdSQL As New SqlCommand(query)
cmdSQL.Parameters.Add("#date", SqlDbType.Date).Value = previousMonthDateToday
cmdSQL.Parameters.Add("#PFOM", SqlDbType.Date).Value = previousFirstOfMonth
pmtdChart.Series(0).ChartType = SeriesChartType.Column
pmtdChart.Series(1).ChartType = SeriesChartType.Column
pmtdChart.Legends(0).Enabled = True
pmtdChart.Series(0).XValueMember = xMember1
pmtdChart.Series(1).XValueMember = xMember2
pmtdChart.Series(0).YValueMembers = "Actual"
pmtdChart.Series(1).YValueMembers = "Projected"
lblPMTDprojected.Text = pmtdChart.Series(1).ToString()
lblPMTDbilled.Text = pmtdChart.Series(0).ToString()
pmtdChart.DataSource = GetData(cmdSQL)
pmtdChart.DataBind()
The GetData Function takes the query above and populates a DataTable, I don't know if I can pull directly from the Datatable within my function and I'm not terribly sure how I would do that, or If I need to pull the value from the chart that I am using.
I have tried the following in the Chart Code:
label.Text = Chart.Series(0).ToString
label.Text = Chart.Series(0).Points(0).ToString()
label.Text = Chart.Series(0).YValueMembers("Actual").ToString
label.Text = Chart.Series(0).YValueMembers(0).ToString
The first quite simply pulls the text value I have assigned to
pmtdChart.Series(0).YValueMembers = "Actual"
The second returns an exception error stating "Index was out of range. Must be non-negative and less than the size of the collection."
The Third returns an exception stating "Conversion From String "Text" to Type "Integer" is not valid.
And the fourth simply returns the first character of "Actual"
Technically I can simply pull this value from my database and assign it to the label, but I am wondering if there is a way to just snag it from my chart so I don't have to query the db again, considering I am using a similar query to populate the chart in the first place.
Any help or tips regarding this issue would be greatly appreciated and I feel like there should be a way to do what I am trying to do. If more information is needed I would be happy to supply it.
I was able to solve the problem I was having above by creating a second data table outside of the GetData() function and then using the GetData() function to populate the second data table. This allowed me to access the specific row/column that held the value I needed
actual = dt.Rows(0)("Actual").ToString()
projected = dt.Rows(0)("Projected").ToString()
I was then able to use these specific values where I needed them outside of the GetData() function.

Want to set dropdown list to the first value in a datatable asp.net

I have a drop down list, GroupDropDown, and a data table, GroupDataTable. I have a select statement that only produces one value, i want to set the drop down selected value to the one value in the data table. I've tried a bunch of different stuff and still can't seem to figure it out. Like most errors, I'm sure I am making a silly mistake, but here is my code:
Dim Region As String = Encryption64.Decrypt(Request.QueryString("Region"))
Dim MySqlString As String = "Select GROUPNAME, GROUPOWNERSHIP from Table1 where GROUPNAME like '%" & Region & "%'"
Dim GroupDataTable As DataTable = OleFun.GetMyDataTableString(MySqlString, 2)
GroupDropDown.DataSource = GroupDataTable
GroupDropDown.DataBind()
For Each row As DataRow In GroupDataTable.Rows
Response.Write(row(1))
Next
GroupDropDown.SelectedValue = ?
GetData()
Thanks in advance for your responses
You can select a row and column from a DataTable by name or index and use that value as the SelectedValue
GroupDropDown.SelectedValue = GroupDataTable.Rows[0]["myColumn"].ToString();
//or by column index
GroupDropDown.SelectedValue = GroupDataTable.Rows[0][7].ToString();
VB
GroupDropDown.SelectedValue = GroupDataTable.Rows(0)("myColumn").ToString

How to select rows from a DataTable where a Column value is within a List?

Say you had a table in SQL and you wanted to find all the rows where a particular column could be one of 3 options. You could write something like this:
SELECT * FROM MyTable WHERE uid IN (123, 456, 789)
That's effectively what I want to do with a DataTable in VB. I saw this post:
Query rows that the datatable field contain any item in the list<string>
Which seemed to be exactly what I wanted, but it's not working as I expected it to. I basically just used a C# -> VB converter and plugged in my variables and came up with this:
Dim item = From a In dtCodes.AsEnumerable() Where
lstCodes.Any(Function(x) a.Field(Of String)
("Code").ToUpper().Contains(x.ToUpper())) Select a
dtCodes is a DataTable with a column Codes in it. lstCodes is a List(Of String) with some values in it.
item just has all of the rows from dtCodes though, regardless of whether or not their Code column value exists in lstCodes.
What am I missing?
edit; Note that I don't have to use LINQ, if there's an easier or better way.
In the past, I've done this sort of like this:
Dim item = From r as DataRow in dtCodes.Rows
Where lstCodes.contains(r.Item("Codes"))
Select r
Does that work?
The code you have looks ok to me. I tried out this test and it (correctly) prints out
a2
b1
Dim dtCodes As New DataTable
dtCodes.Columns.Add(New DataColumn("Code"))
dtCodes.Rows.Add("a1")
dtCodes.Rows.Add("a2")
dtCodes.Rows.Add("b1")
dtCodes.Rows.Add("b2")
Dim lstCodes As New List(Of String)
lstCodes.Add("b1")
lstCodes.Add("c1")
lstCodes.Add("a2")
Dim item = From a In dtCodes.AsEnumerable()
Where lstCodes.Any(Function(x) a.Field(Of String)("Code").ToUpper().Contains(x.ToUpper()))
Select a
For Each itm In item
Debug.WriteLine(itm("Code").ToString)
Next
Here's a lamba expression that should also work.
Dim item = dtCodes.Select.Where(Function(x As DataRow) lstCodes.Contains(x.Item("Codes")))

Populate DropDownList with ArrayList set Text and Data Fields

I am trying to populate a dropdownlist with queried data based on the selection of another dropdownlist. My first query returns a list of IDs using the following code:
Dim selectQuery = (From train In trainerEntities.TrainerTrainingCompanies
Where train.TrainingCompanyID = trainingCompany.ID
Select train.TrainerID).ToList()
I then create an arraylist and a second query
Dim trainers As New ArrayList
For Each trainerID In selectQuery
Dim selectQuery2 = (From pers In trainerEntities.Persons
Where pers.Person_ID = trainerID
Select pers.Person_ID, pers.Last_Name).ToList()
trainers.Add(selectQuery2)
Next
Finally I use the arraylist as a datasource and bind the data
TrainerDropDownList.DataSource = trainers
TrainerDropDownList.DataBind()
The list populates, but not with any data. It looks like this:
System.Collections.Gerneric.List'1[VB$AnonymousType_0'2[System.Int32,System.String]]
When debugging and looking at the array list I see the proper amount of items and the proper information in each specific item. Looking at what the list is populated with from above I am sure the Int32 value is the Person_ID and what I want to use for the dropdownlist value field and the String value is the Last_Name and what I want to used for the dropdownlist text field.
Using:
dropdownlist.DataTextField("Last_Name")
dropdownlist.DataValueField("Person_ID")
produces and error on databind.
does not contain a property with the name 'trainers.Last_Name'
How do I properly use this arraylist as my datasource for my dropdownlist
I rethought how I was gathering the data on selectQuery2. Instead of looping through the results, I altered the "where" clause of the LINQ query to what I believe is a called a lambda expression. This allows me to use my select query and match the person IDs.
Dim selectQuery2 = (From pers In trainerEntities.Persons
Where selectQuery.Any(Function(x) pers.Person_ID.Equals(x))
Select pers.Person_ID, pers.Last_Name).ToList()
The where clause now essentially says select where Person_ID = any of the original selectQuery results.
From here selectQuery2 can be used as the data source with Last_Name and Person_ID as the text and value fields.
TrainerDropDownList.DataSource = selectQuery2
TrainerDropDownList.DataTextField = "Last_Name"
TrainerDropDownList.DataValueField = "Person_ID"
TrainerDropDownList.DataBind()

ASP VB NET List(of T) find method failing in a for each loop

Good morning stackers!
I'm designing a massive update page. Here are the general steps:
I have a class called item which has two properties: Equipment number and new due date.
I have a textbox where i paste values from Excel, the values consist of two columns divided by a vbtab character: the columns are an equipment number and a new due date
A button is clicked and the values from textbox are parsed into a list(of item) and the equipment master builds a string for an SQL criteria for a commandtext.
The command fills a dataset from a database which gets equipment number and current due date.
I add manually a column to the dataset (new due date)
I iterate over the rows of the dataset, and i use the list(of item) find method matching equipment from the list and from the database to get a new due date from the textbox parsed values.
Everything is going well, except that when using the find method for more than 1 row in the dataset, the method fails:
Here is the code from point 5 and 6:
da.Fill(ds, "Equipments")
dt = ds.Tables(0)
ds.Tables(0).Columns.Add("column_1", Type.GetType("System.DateTime"))
Dim rw As DataRow
For Each rw In ds.Tables(0).Rows
Dim strsearch As String = rw(0).ToString
Dim fequnumb As item = myItemList.Find(Function(p) p.EquipNumber = strsearch)
rw(2) = fequnumb.DueDate <- Error occurs here
Next
Again, if instead of ftechid.DueDate I put a static value like Today()the code runs fine for the loop and fills correctly the gridview, but if i leave the ftechid.DueDate then an error is thrown after the first row:
Object reference not set to an instance of an object.
Any help is very much appreciated as to how to use the find method inside a for..each loop
If the Find function cannot match the string requested it returns Nothing and then you cannot set the due date from a variable that is Nothing. If this is a condition expected from the input then you need to protect the assignment to the new column with something like this.
For Each rw In ds.Tables(0).Rows
Dim strsearch As String = rw(0).ToString
Dim fequnumb As item = myItemList.FirstOrDefault(Function(p) p.EquipNumber = strsearch)
if fequnumb IsNot Nothing Then
rw(2) = fequnumb.DueDate <- Error occurs here
End if
Next
If this is not supposed to happen then you need to check your inputs

Resources