Linq query exception/error - vb.net

Following is the code I get to achieve a list of Courses:
Dim Result As New List(Of WorkMateLib.CourseNameSpace.CoursesLib.Course)
For Each cat As WorkMateLib.CourseNameSpace.CoursesLib.Category In Courses.CoursesOfferedMAIN.Values
For Each c As WorkMateLib.CourseNameSpace.CoursesLib.Course In cat.Courses.Values
Result.Add(c)
Next
Next
and it is working fine. However I am trying to attempt to do the same with linq and the code is:
Result.AddRange(From k As WorkMateLib.CourseNameSpace.CoursesLib.Category In Courses.CoursesOfferedMAIN.Values Where Not k.CategoryName = "" Select k.Courses.Values.ToList())
But is throwing an error as follows:
Unable to cast object of type
'WhereSelectEnumerableIterator2[WorkMateLib.CourseNameSpace.CoursesLib+Category,System.Collections.Generic.List1[WorkMateLib.CourseNameSpace.CoursesLib+Course]]'
to type
'System.Collections.Generic.IEnumerable`1[WorkMateLib.CourseNameSpace.CoursesLib+Course]'.
Could you please help me better understand it. Thank you.

This should be equivalent. Note that there's no need to create a list yourself.
Dim Result = Courses.CoursesOfferedMAIN.Values _
.SelectMany(Function(cat) cat.Courses.Values) _
.ToList

Related

Binding VB.net DataRepeater to dataview items at runtime with aggregation using linq

Hoping someone can help me out with what is probably a dumb question.
I'm trying to use a datarepeater to display data generated via LINQ from a datatable
I've managed to do this fine with a filtered existing datasource using:
Me.Tbl_52TableAdapter.Fill(Me.CBRDataSet.tbl_52)
Dim query =
From dlist In CBRDataSet.tbl_52.AsEnumerable
Where (dlist.Field(Of String)("TL") = "CTS 06")
Select dlist
query.CopyToDataTable().AsDataView()
DataRepeater1.DataSource = query
The problem being that I need to aggregate a field in the dataset into a count.
If I replace the query with:
Dim query =
From CountAgent In CBRDataSet.tbl_52.AsEnumerable
Group CountAgent By PBX = CountAgent.Field(Of String)("TL") Into Count()
Select Count
It then states that:
'CopyToDataTable' is not a member of 'System.Collections.Generic.IEnumerable(Of Integer)'
I've tried to get around it by changing the declaration to:
Dim query As IEnumerable(Of DataRow) =
Which compiles, but I have no idea if it works, and I cant check as I can't find a way to bind a label to the produced count col of the dataview.
If anyone can tell me what I'm doing wrong i'd be most appreciative.
Coming back to my own question, in case it helps anyone else: MSDN had the answer -
You need to overload copyToDataTable as described in
"How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow"
on:
http://msdn.microsoft.com/en-us/library/bb669096.aspx

How do I pass ItemSpec into GetBranchHistory()?

I'm trying to get information about specific branches in TFS, so to start, I'm trying to create a variable to assign as a BranchHistoryTreeItem. However, when I pass in the ItemSpec, I'm getting an error on Spec (not the definition, but where it's passed into GetBranchHistory):
Value of type 'Microsoft.TeamFoundation.VersionControl.Client.ItemSpec' cannot be converted to '1-dimensional array of Microsoft.TeamFoundation.VersionControl.Client.ItemSpec'
I understand the error, but I'm not entirely sure why it throwing it. Isn't this data type exactly what it's looking for? I believe I have the ItemSpec declared correctly, but I'm a bit lost here. Can anyone offer some advice on why I'm getting this? Code:
Sub GetBranchInfo()
Dim tfs As New TfsTeamProjectCollection(Common.BuildServerURI)
Dim Version = tfs.GetService(Of VersionControlServer)()
Dim Spec As New ItemSpec("$/Project1", RecursionType.None)
Dim BranchHistory As New BranchHistoryTreeItem(Version.GetBranchHistory(Spec, VersionSpec.Latest))
End Sub
GetBranchHistory takes an array of ItemSpecs.
My VB is a little rusty, but I think you want something like:
Dim Spec As New ItemSpec("$/Project1", RecursionType.None)
Dim Specs(1) = new ItemSpec() {Spec}
Dim BranchHistory As New BranchHistoryTreeItem(Version.GetBranchHistory(Specs, VersionSpec.Latest))

LINQ VB.Net variable not declared error

I am trying to run this line of code:
Dim OrderedFiles() As String = Directory.GetFiles(FilePath).OrderBy(x >= x.CreationTime)
I get an error on x saying x is not declared.
I have my project set to Option Strict Off and Option Infer On. If I turn ON Option Strict then I get thousands of errors from the project(it is inherited) and I don't have the time to fix all of them, but x no longer gives me an error. I have googled until I want to throw my computer out the window.
Any help on how to correct this statement would be appreciated.
Edit:
I was hoping for a more elegant solution but here is what I came up with to solve this particular problem.
Dim fileList() As String = Directory.GetFiles(FilePath)
Dim fileDate(fileList.Length - 1) As DateTime
For i As Integer = 0 To fileList.Length - 1
fileDate(i) = New FileInfo(fileList(i)).CreationTime
Next
Array.Sort(fileDate, fileList)
With EmailTemplates_DropDownList
.DataSource = fileList.Reverse.Take(5)
.DataBind()
End With
It is not particularly elegant but it does the job. I was hoping for a one liner LINQ solution and I just don't have the background in LINQ to know how to do the job, time to go buy a book.
I'm not sure where you got this syntax from:
OrderBy(x >= x.CreationTime)
That almost looks like the C# syntax of
OrderBy(x => x.CreationTime)
but I believe in VB you would use
OrderBy(Function(x) x.CreationTime)
That's certainly what the example in Enumerable.OrderBy would suggest.
EDIT: At that point you'll get a different error, as per Steve's post... but he hasn't corrected the syntax. I suspect you want:
Dim OrderedFiles() As FileInfo = new DirectoryInfo(FilePath).GetFiles().
OrderBy(Function(x) x.CreationTime).
ToArray()
Directory.GetFiles() returns the names of files (including their paths) in the specified directory.
It's not possible to use x.CreationTime, x is a string
Probably you should use DirectoryInfo
Dim di as DirectoryInfo = new DirectoryInfo(FilePath)
Dim OrderedFiles = di.GetFiles().OrderBy(Function(x) x.CreationTime).Take(3)
Dim fi as FileInfo
For each fi in OrderedFiles
Console.WriteLine(fi.FullName)
Next

VB Syntax for LINQ query that creates a new{} set?

I am trying to AVERAGE 6 different fields on a DataTable, but without grouping. Just the AVERAGE. I have found a couple of examples in C#, but can't find any examples for how to do this in VB. Can someone please help me convert the syntax?
Here is what I have so far:
Dim query = From dtRow In dtIn.AsEnumerable _
Where dtRow.Field(Of String)("FOLLOWUP") = "Alert" _
Select New With { _
.Brand_Functional_Avg = XXX.Average(Function(f) f("Brand_Functional")), _
.Brand_Personal_Avg = XXX.Average(Function(f) f("Brand_Personal")) _
}
What should I use for XXX? I tried all of the options that I could think of and nothing is compiling.
Trust me, if I could write this in C#, I would, but the project requires VB.
If you're trying to find the average, you shouldn't be using a select to start with - that's going to create a new result for each row, whereas you want just two results for the whole table. I suggest you do something like:
Dim filtered = From dtRow in dtIn.AsEnumerable _
Where dtRow.Field(Of String)("FOLLOWUP") = "Alert"
Dim functionalAvg = filtered.Average(Function(f) f("Brand_Functional"))
Dim personalAvg = filtered.Average(Function(f) f("Brand_Personal"))

Adding Nodes to Tree via LINQ creates "query operator not supported" during runtime

I am trying to get my head around a LINQ issue. The ultimate goal is to load tree view with data acquired from LINQ to SQL (view). The issue is when I try to access the data acquired it keeps throwing a "query operator not supported during runtime". The code involved is no more than:
Dim tasklistdata As New lqDataContext
Dim UserID As Integer
UserID = (From vwUser In tasklistdata.Operators _
Where vwUser.UserName Is Login.txtUsername.Text _
Select vwUser.OperatorID).Single
Dim lqHospitalList = From vwHospitalList In tasklistdata.SPM_Accounts _
Where vwHospitalList.OperatorID = UserID _
Order By vwHospitalList.CustomerName, vwHospitalList.Class _
Select vwHospitalList.CustomerName, vwHospitalList.Class, vwHospitalList.ClassCount, vwHospitalList.Charges
tvHospitalSelect.Nodes.Add(lqHospitalList(0).CustomerName)
if I were to change the code to lqHospitalList.First.CustomerName it works as expected, however changing it to array position is where the issue arises. Please direct me to where my flaw in logic is.
Linq querys are not lists, so they don't have an index. To iterate over all the items you can use a foreach like so:
For Each hospital In lqHospitalList
tvHospitalSelect.Nodes.Add(hospital.CustomerName)
Next
If you want to convert the query to a list:
lqHospitalList.ToList
or array:
lqHospitalList.ToArray