VB Syntax for LINQ query that creates a new{} set? - vb.net

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"))

Related

Linq query exception/error

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

Building a dynamic LINQ query

I have a listbox which users can select from a list if Towns, I want to be able to build a LINQ query based on the selected items in the list e.g.
Dim ddlTowns As ListBox = CType(Filter_Accommodation1.FindControl("ddlTowns"), ListBox)
If Not ddlTowns Is Nothing Then
For Each Item In ddlTowns.Items
If Item.Selected Then
'// Build query
End If
Next
End If
I have researched LinqKit as it appears to be able to do what I need but I cannot after hours of trying make any headway. I cannot find anything in VB which translates in anything meaningful or usable.
Just had a Eureka moment and rather than using predicate I came up with this...
Private Function Filter_Accommomdation_QueryBuilder() As IEnumerable
Dim ddlTowns As ListBox = CType(Filter_Accommodation1.FindControl("ddlTowns"), ListBox)
Dim myList As New List(Of String)
If Not ddlTowns Is Nothing Then
For Each Item In ddlTowns.Items
If Item.Selected Then
myList.Add(Item.value)
End If
Next
End If
Dim Filter_Query = _
From c In InitialQuery _
Where myList.ToArray.Contains(c.MyData.element("townvillage").value) _
Select c
Return Filter_Query
End Function
As a note I'm using c.MyData as the nature of InitialQuery demands a number of structured fields (the query is reused from various tables which by poor design aren't very consistant).
Check out this question - contains some useful VB examples for you: Using PredicateBuilder with VB.NET

Converting System.Linq.IorderedEnumerable to DataView

I am trying to get the DataView from a linq query expression which is querying a typed dataset. The result lands in a type of System.linq.IOrderedEnumerable. But i'm not able to convert this type to a Dataview although a few examples on the internet say that AsDataView function shoudl work but could you please throw some light on why the method AsDataView is not exposed on the query.
example code:
Dim SortedRates = From rateDetail In ratesDetail _
Select RateName = ("(" & rateDetail.RateType & ") - " & rateDetail.Name), _
RateID = rateDetail.RateID _
Order By RateName Ascending
Dim dv1 As New DataView
dv1 = SortedRates
I cannot do SortedRates.AsDataView and i also cannot directly cast SortedRates to dv1.
Please help.
Thanks.
Khurram.
The AsDataView method only applies to collections of DataRows.
What you're trying to do is impossible because a DataView must wrap a DataTable.
The only way to do this is to create a DataTable from your query and make a DataView for that DataTable.
Why do you need a DataView?

Is it possible to change & to & in the results from a LINQ query?

I have the following code:
Dim db As New linqclassesDataContext
Dim categories = (From c In db.faq_cats)
NewFaqDropDownCategory.DataSource = categories
NewFaqDropDownCategory.DataTextField = "category"
NewFaqDropDownCategory.DataValueField = "category_id"
If Not Page.IsPostBack Then
NewFaqDropDownCategory.DataBind()
End If
Unset(categories)
Unset(db)
One of the items under the column "category" has & in the title, and that shows up in the dropdownlist as such. Is there someway to make the list display "&" instead?
One Solution
I figured I could use the .Replace() function to do this, and I accidentally found out how:
For Each c In categories
If c.category.Contains("&") Then
c.category = c.category.Replace("&", "&")
End If
Next
I could expand this in the future to process other values as well.
If there are other HTML encoded characters in there as well you could use HttpUtility.HtmlDecode(c.category). This would prevent your replace and ensure that any characters are properly decoded.
I don't know if this is exact VB linq anonymous object syntax, but I tried.
Dim datasource = From categories In db.faq_cats _
Select New With { .category = HttpUtility.HtmlDecode(categories.category), .category_id = categores.category_id }
Then bind your DDL to that datasource.
You could also just use .Replace if you only need &
Dim datasource = From categories In db.faq_cats _
Select New With { .category = categories.category.Replace("&", "&"), .category_id = categores.category_id }
One of the items under the column "category" has & in the title
If that & is really supposed to be a ‘&’, I suggest your database needs cleaning to make it one. Generally you always want plain text in your database; the HTML-escaping shouldn't happen until the final output-to-page stage.
Storing data in different stages of encoding is confusing and potentially dangerous to work with; get the wrong level of encoding in the other direction and you have cross-site-scripting attacks.
I suggest you do .ToList(), and then have a Select that grabs it doing .Replace()
The reason to do ToList, is to get it as on memory, from then on you get to are no longer constrained to constructs that exists on sql. I don't know the vb.net syntax, but in c# the select would look like:
new {
category = c.category.Replace("&", "&"),
c.category_id
}

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