Determine the type of Object to use to store a Linq Query - vb.net

I am using VB .Net for this, so I don't have access to var or this would be a simple matter.
Right now my query is as follows
Dim errors As IOrderedQueryable(Of IGrouping(Of String, RSError)) = (From e In db.RSErrors
Where e.UserID = "msarchet"
Group e By e.Type Into t = Group).AsEnumerable
So I used this query in LinqPad to help me determine what the object would look like. I got back a IOrderQueryable(Of RSError) which then contained a IGrouping(Of String, RSError) for each grouped collection of objects returned by the query.
However I ended up with the current object type of errors as IOrderedQueryable(Of IGrouping(Of String, RSError)) because of the cast error I am getting in VS.
Unable to cast object of type 'System.Data.Linq.DataQuery1[VB$AnonymousType_12[System.String,System.Collections.Generic.IEnumerable1[RSSAdmin2.RSError]]]' to type 'System.Linq.IOrderedQueryable1[System.Linq.IGrouping2[System.String,RSSAdmin2.RSError]]'.
I'm not sure how to get rid of the VB$AnonymousType_1 Part of the returned object.
Am I even on the right track here or am I missing something completely?

Can you try the following
Dim errors = (From e In db.RSErrors
Where e.UserID = "msarchet"
Group e By e.Type Into t = Group).AsEnumerable
Doing it this way basically sets it to
Dim errors As Object [Whatever the expression returns]

Related

Converting LINQ to dictionary in vb.net

I'm trying to convert LINQ to dictionary in vb.net, but can't seem to understand why I get all these exceptions thrown at me.
All I'm trying to do, is to sort by descending value with help from LINQ.
Here's my code:
'Declaring my primary dictionary
Dim nameValDict As New Dictionary(Of Object, Object)
... nameValDict is now getting filled up with data
'Declaring temporary sorted dictionary with LINQ
Dim sortedDict = (From entry In nameValDict Order By entry.Value Descending Select entry)
'Replace with sorted results from LINQ
nameValDict = sortedDict.ToDictionary(Function(x) x.Key, Function(x) x.Value)
Exception: System.ArgumentException (Object should be of type Double) - On last line.
I'll appreciate ANY help.
Its properly your Order By in this statement:
From entry In nameValDict Order By entry.Value Descending Select entry
Becuase entry.Value is of type Object, and you can't sort desending on Object. The program doesnt know how to compare Objects against eachother.

Where clause in LINQ query is not recognized in vb.net?

The entity field is not recognized in the following Where clause. Is the VB wrong?
Dim projects = context.projects
.OrderBy(Function(x) x.name)
.Select(Function(x) {x.id, x.name})
.Where(Function(x) x.id <> sourceid)
If I take the Where off, it works fine. Also, if I flip the Where and the OrderBy, Where is fine, but now OrderBy fails.
Try this:
Dim projects = context.projects
.OrderBy(Function(x) x.name)
.Select(Function(x) New With {x.id, x.name})
.Where(Function(x) x.id <> sourceid)
The New With keyword should create an IEnumerable of anonymous type. You can then work with the id property in the Where clause without having to change the order of your operations.
There is nothing stopping you from doing the operations OrderBy, Select, Where in that order. The above code will certainly compile and run. However, logically you need to do the Where before Select, since the former is a filtering operation, while the latter is a projection.
Can you please try with the below code snippet.
Dim projects = context.projects.Where(Function(x) x.id <> sourceid).OrderBy(Function(x) x.name).Select(Function(x) {x.id, x.name})
This {x.id, x.name} is most likely an array of object (assuming id is integer and name is string, VB would infer Object). It is not an instance of a class with properties of id and name. #shree.pat18 explained how it can be adjusted to return what you want, but I would suggest using query syntax for clarity, and also putting your where clause before Select (should be slightly faster, because it does not create anonymous objects from the values you don't need included in results):
Dim projects = From p In context.projects
OrderBy p.name
Where p.Id <> sourceid
Select Id = p.Id, Name = p.Name

Error when using linq on datatable

I am trying to run the following code converting my datatable to be usable in linq all seems fines and compiles but when I Execute the statement I get the following statement i get the error below new entires just has location and ordernumber in the return values I have to do it this way as I am supporting a legacy access 97 system thanks.
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int32)("location") Distinct
retVal = Convert.ToInt32(total)
This is my whole code but im still getting an invalid type cast error their is data exsits for this order by teh way
Dim retVal As Int32
Dim newEntries As New DataTable
Dim script As String = scriptBuilder.GetDistinctOrdersForLocations(OrderNumber)
newEntries = connection.SqlSelectToDataTable(script)
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int32)("location") Distinct
retVal = total.Count()
If you want the count of the collection just do this:
retVal = total.Count()
this will return the count from the distinct query that you have written.
Just to clarify, #David B identified the data type of location was int16 not int32, so changing this in the linq query resolved the issue.
Your LINQ query is returning a collection. You should use something like First or FirstOrDefault.
I'm a little rusty on VB LINQ, but try :
retVal = Convert.ToInt32(total.First())
Note: This will throw an error if there are no items in the collection.
It's important to understand when you write a LINQ query and assign it to a variable, that variable essentially contains a query object, and not the results of running the query. In order to get the value that results from the query, you need to call some method on the query object such as:
total.Single() ' Assumes you expect the query to return exactly one result.
I changed the code to int16 worked here is the code for any one else stuck thanks #Ric
Dim retVal As Int32
Dim newEntries As New DataTable
Dim script As String = scriptBuilder.GetDistinctOrdersForLocations(OrderNumber)
newEntries = connection.SqlSelectToDataTable(script)
Dim total = From row In newEntries.AsEnumerable()
Select row.Field(Of Int16)("location") Distinct
retVal = total.Count()

"Runtime errors might occur when converting 'system.linq.IQueryable(of String)' to 'String'

I am creating a feature where I allow a user to type in an email address and click "Search". This will search my database and return the email address, which I will then use in other methods to randomly generate passwords and email them. Language is ASP.VB and database is LINQ. I am getting an error to say "Runtime errors might occur when converting 'system.linq.IQueryable(of String)' to 'String' "
The code segment is:
Protected Sub btnSearchEmail_Click(sender As Object, e As System.EventArgs) Handles btnSearchEmail.Click
Dim db As New DatabaseDataClassesDataContext()
GlobalVariables.SearchUserEmail = txtSearchEmail.Text
GlobalVariables.CurrentEmailAddress = (From u In db.User_Signons
Where u.Email = SearchUserEmail
Select u).Distinct
End Sub
Any thoughts on how I can get around this. The global variables are both "As String" and the field in the DB is varchar. Thanks in advance
The Distinct call returns a sequence of strings, and the property you are assigning to is just one single string. Consider using First or FirstOrDefault instead of Distinct.
The problem is here:
GlobalVariables.CurrentEmailAddress = (From u In db.User_Signons
Where u.Email = SearchUserEmail
Select u).Distinct
Distinct returns a collection of distinct values. If you just want one value use
var user = (From u In db.User_Signons
Where u.Email = SearchUserEmail
Select u).First
GlobalVariables.CurrentEmailAddress = user.Email
' Do something with password
Note that :
This only gives you the first value (obviously)
It will throw an exception if there are NO results (use FirstOrDefault to return a default value (null for strings) if that is a legitimate possibility.

Perform an aggregation on a DataTable with Linq in vb.net

Given a datatable, I wish to output an IEnumerable type (dictionary(of T) would be perfect, otherwise a datatable would be acceptable) that provides an aggregation of the data within the datatable.
In SQL I would write the query as such:
select groupByColumn, sum(someNumber) from myTable group by groupByColumn
In VB.NET the closest I have got to this (achieved using information here) is:
' dt is a datatable containing two columns, referred to by index in p below
Dim q = From p In dt Group p By p(0) Into Sum(p(1)) Select p(0), SumOfNumber = Sum
However I receive error: "Range variable name can be inferred only from a simple or qualified name with no arguments." on the p(0) element.
Therefore my question is as follows:
How can I resolve this error?
How do I process the result (q) as an IEnumerable type?
Life isn't made any easier because I'm using Linq in unfamiliar vb.net. Many examples are in C#, but I haven't really come across anything suitable even in C#.
Resolved: I had to alias the columns returned.
Dim q = From p In dt
Group p By transactionTypeName = p(0) _
Into totalForType = Sum(Convert.ToDouble(p(1))) _
Select transactionTypeName, totalForType
Also note that I had to do a conversion on the value that I was summing because being a dynamically returned datatable didn't have the column type specified.
Hint found here because vb.net oh so helpfully gives us a different error message to C#'s "Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access."
For completeness, results are processed as below:
For Each item In q ' no need for defining item as a type (in C# we'd use the var keyword)
If item.totalForType = magicNumber Then
'do something
Else
'do something else
End If
Next