'Order by' ignored in LINQ query - vb.net

I am trying to sort a list by company name. I have tried the following code but this sorts the list by CompID and not CoShort. How should I change this to sort by CoShort?
Public Shared Function [SelectCompanyData](iElement() As Integer) As List(Of CompanyList)
Dim db As New EntryDataContext()
Dim q As IQueryable(Of CompanyList) = (From Act_Sub_Manfu_Link In db.Act_Sub_Manfu_Links _
Join Company In db.Companies _
On Act_Sub_Manfu_Link.CompID Equals Company.CompID _
Where iElement.Contains(Act_Sub_Manfu_Link.ACCN) _
And Company.In_Dir _
Select New CompanyList With { _
.CompID = Company.CompID, _
.InDir = Company.In_Dir, _
.CoShort = Company.CoShort _
}).Distinct
q.OrderBy(Function(c) c.CoShort)
Dim list As List(Of CompanyList) = q.ToList
Return list
End Function

You have to assign ordered collection into a variable:
Dim oq As IOrderedQueryable(Of CompanyList) = q.OrderBy(Function(c) c.CoShort)
And use it to get List of results:
Dim list As List(Of CompanyList) = oq.ToList()

Doesn't need to be assigned to anything but the return value
Public Function SelectCompanyData(iElement() As Integer) As List(Of CompanyList)
Dim db As New EntryDataContext()
Return (From Act_Sub_Manfu_Link In db.Act_Sub_Manfu_Links _
Join Company In db.Companies _
On Act_Sub_Manfu_Link.CompID Equals Company.CompID _
Where iElement.Contains(Act_Sub_Manfu_Link.ACCN) _
And Company.In_Dir _
Select New CompanyList With { _
.CompID = Company.CompID, _
.InDir = Company.In_Dir, _
.CoShort = Company.CoShort _
}).Distinct().OrderBy(Function(c) c.CoShort).ToList()
End Function

Related

object Collection Containing a List of IDs Linq

I have a list box and the user is able to multi-select. I want to use Linq and bring back the records of the selected IDs that the user selects. I need to bring back the full object record for each selected ID
Here is the contact object along with collection object
Namespace MODEL
<System.Serializable()> _
Public Class ContactCollection
Inherits System.Collections.ObjectModel.Collection(Of Contact)
Implements IList(Of Contact)
End Class
End Namespace
Namespace MODEL
<System.Serializable()> _
Public Class Contact
Private mContactID As Int32 = 0
Private mFirstName As String
Private mLastName As String
Public Property ContactID As Int32
Get
Return mContactID
End Get
Set(value As Int32)
mContactID = value
End Set
End Property
Public Property FirstName As String
Get
Return mFirstName
End Get
Set(value As String)
mFirstName = value
End Set
End Property
Public Property LastName As String
Get
Return mLastName
End Get
Set(value As String)
mLastName = value
End Set
End Property
End Class
End Namespace
Adding 5 Records to the collection object
Dim objCollection As New MODEL.ContactCollection
Dim obj As New MODEL.Contact
objCollection.Add(New MODEL.Contact With {
.ContactID = 1, _
.FirstName = "John", _
.LastName = "Smtih" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 2, _
.FirstName = "Mark", _
.LastName = "Davis" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 3, _
.FirstName = "Tom", _
.LastName = "Howe" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 4, _
.FirstName = "Jerry", _
.LastName = "Thomas" _
})
objCollection.Add(New MODEL.Contact With {
.ContactID = 5, _
.FirstName = "Jane", _
.LastName = "Marry" _
})
This is the selected contact List from the list box
Dim lstContacts As New List(Of Integer)
lstContacts.Add(2)
lstContacts.Add(4)
I am not sure what to do at this point with Linq to find the values. I think I have to use contains but I have tried may different ways but I was unable to get the values.
I have tried this Linq but does not work or bring any records back
Dim objSearch from SearchContacts in objCollection
Where (lstContacts.Contains(SearchContacts.ContactID))
To get the Ids, try that :
Dim ids As IEnumerable(Of Int32) = myListBox.SelectedItems _
.OfType(Of Contact)() _
.Select( Function(c) c.ContactID ) _
Edit
If you want the Contacts, you can just just :
Dim ids As IEnumerable(Of Contact) = myListBox.SelectedItems _
.OfType(Of Contact)()
And if you want the contacts in a separate copied collection, you can :
Dim ids As List(Of Contact) = myListBox.SelectedItems _
.OfType(Of Contact)() _
.ToList()
Last (if think this is your real question - just tell and I erase everything above)
Dim selectedContacts As IEnumerable(Of MODEL.Contact) = From contact In objCollection
Join id In lstContacts
On contact.ContactID Equals id
Select contact

Linq query to array

This is currently my Linq query:
result = From d In dc.Tracker
Where d.Responsible.Value = "first last name"
Order By d.Priority1, d.Deadline
Select New With { _
Key .Title = d.Name, _
Key .Description = d.Priority1, _
Key .Priority2= d.Priority2, _
Key .Status = d.Status, _
Key .Resp= d.Resp, _
Key .Deadline = d.Deadline, _
Key .Notes = d.Notes, _
}
I am trying to output the data but can only seem to do so doing this:
For Each d In result
Console.WriteLine(d)
Next
But i can not seem to place it into an array so that i can call it like this:
result(0), result(1), etc etc...
Or even better:
result.Title, result.Description, etc etc...
How can i change that linq into an array?
Use the .ToArray() method.
result = (From d In dc.Tracker
Where d.Responsible.Value = "first last name"
Order By d.Priority1, d.Deadline
Select New With { _
.Title = d.Name, _
.Description = d.Priority1, _
.Priority2= d.Priority2, _
.Status = d.Status, _
.Resp= d.Resp, _
.Deadline = d.Deadline, _
.Notes = d.Notes}).ToArray()
Got it working at least how i am needing it too:
Dim Title As New ArrayList
Dim Description As New ArrayList
Dim Priority2 As New ArrayList
Dim Status As New ArrayList
Dim Resp As New ArrayList
Dim Deadline As New ArrayList
Dim Notes As New ArrayList
result = From d In dc.Tracker
Where d.Responsible.Value = "first last name"
Order By d.Priority1, d.Deadline
Select New With { _
Key .Title = d.Name, _
Key .Description = d.Priority1, _
Key .Priority2= d.Priority2, _
Key .Status = d.Status, _
Key .Resp= d.Resp, _
Key .Deadline = d.Deadline, _
Key .Notes = d.Notes, _
}
For Each d In result
If Not IsNothing(d.Title()) Then Title.Add(d.Title()) Else Title.Add("NA")
If Not IsNothing(d.Description()) Then Description.Add(d.Description().value) Else Description.Add("NA")
If Not IsNothing(d.Priority2()) Then Cost.Add(d.Priority2().value) Else Priority2.Add("NA")
If Not IsNothing(d.Status()) Then Status.Add(d.Status().value) Else Status.Add("NA")
If Not IsNothing(d.Resp()) Then Responsible.Add(d.Resp().value) Else Resp.Add("NA")
If Not IsNothing(d.Deadline()) Then Deadline.Add(d.Deadline()) Else Deadline.Add("NA")
If Not IsNothing(d.Notes()) Then Notes.Add(d.Notes()) Else Notes.Add("NA")
Next

Group By LINQ Dyanmic Query

I am trying to allow the user to change the query dynamically by a querystring parameter. I am having trouble getting the group by to work in vb.net. I am wanting to return the id, name, and count of each group.
' load all of the types
Dim baseQuery = db.Answers _
.Where(Function(a) a.Question.CorrectAnswer <> a.answer) _
.Where(Function(a) a.Question.TypeId = TypeId)
If catId <> 0 Then
baseQuery = baseQuery _
.Where(Function(x) x.Question.CategoryId = catId) _
.ToList()
End If
If approachId <> 0 Then
baseQuery = baseQuery _
.Where(Function(x) x.ApproachId = approachId) _
.ToList()
End If
Dim grouppedQuestionTypesincorrectTotal = baseQuery _
.GroupBy(Function(x) x.Question.TypeId) _
.Select(Function(x) New With {.id = x.id}) _
.ToList()
Dim grouppedCategorieincorrectTotal = baseQuery _
.GroupBy(Function(x) x.Question.CategoryId) _
.ToList()
Dim grouppedApproachesincorrectTotal = baseQuery _
.GroupBy(Function(x) x.ApproachId) _
.ToList()
ViewBag.QuestionTypes = grouppedQuestionTypesincorrectTotal
ViewBag.Categories = grouppedCategorieincorrectTotal
ViewBag.Approaches = grouppedApproachesincorrectTotal

How to use the vb equivalent of ++ for an index property in a Linq query projecting a new type

I'd normally do this in C# but since I've got to get this code in this particular assembly which is a vb.net one, I'm stuck.
Here's my linq query:
Dim i As Integer = 0
Dim oldAndCurrentIntersectionOnNames = From currentApplicant In currentApplicants _
Group Join oldApplicant In oldApplicants _
On _
New With {Key .FirstName = currentApplicant.FirstName, _
Key .LastName = currentApplicant.LastName} _
Equals _
New With {Key .FirstName = oldApplicant.FirstName, _
Key .LastName = oldApplicant.LastName} Into applicants = Group _
From applicant In applicants.DefaultIfEmpty(New ApplicantNameDetails()) _
Select New ApplicantNameDetails() With _
{ _
.Index = i+=1, _
.FirstName = CStr(IIf(Not currentApplicant.FirstName Is Nothing, currentApplicant.FirstName, Nothing)), _
.OldFirstName = CStr(IIf(Not applicant.FirstName Is Nothing, applicant.FirstName, Nothing)), _
.LastName = CStr(IIf(Not currentApplicant.LastName Is Nothing, currentApplicant.LastName, Nothing)), _
.OldLastName = CStr(IIf(Not applicant.LastName Is Nothing, applicant.LastName, Nothing)) _
}
You'll see the .Index = i+=1
This was my attempt to do what I'd quite happily do in C# (i.e. Index = i++) in VB. Unfortunately the VB compiler doesn't like that.
Has anybody got any suggestions as to how I'd do this in VB.
Thanks in advance
Essentially, you can’t. If you want the Linq query to get consecutive values, use a special (so-called “generator”) class that has an IncrementAndGet (or simply Next) method for your integer.
class IntegerGenerator
private state as integer = 0
public function Next() as integer
dim oldState = state
state += 1
return oldState
end function
end class
There is an overload of the Select method that lets you use the index of the item on the result collection. http://msdn.microsoft.com/en-us/library/bb534869.aspx
You could split your query in two parts to use it (untested)
Dim q = From currentApplicant In currentApplicants _
Group Join oldApplicant In oldApplicants On _
New With {Key.FirstName = currentApplicant.FirstName, _
Key.LastName = currentApplicant.LastName} _
Equals _
New With {Key.FirstName = oldApplicant.FirstName, _
Key.LastName = oldApplicant.LastName} Into applicants = Group _
From applicant In applicants.DefaultIfEmpty(New ApplicantNameDetails())
Dim oldAndCurrentIntersectionOnNames = _
q.Select(Function(x, i) New ApplicantNameDetails() With _
{ _
.Index = i, _
.FirstName = CStr(IIf(Not x.currentApplicant.FirstName Is Nothing, x.currentApplicant.FirstName, Nothing)), _
.OldFirstName = CStr(IIf(Not x.applicant.FirstName Is Nothing, x.applicant.FirstName, Nothing)), _
.LastName = CStr(IIf(Not x.currentApplicant.LastName Is Nothing, x.currentApplicant.LastName, Nothing)), _
.OldLastName = CStr(IIf(Not x.applicant.LastName Is Nothing, x.applicant.LastName, Nothing)) _
})

LINQ OrderBy sort Problem

I have a LINQ Query:
bikersList = (From c In ngBikersDataContext.Reg_Bikers _
Order By c.L_Name _
Select New Bikers() With { _
.BikerID = c.BikerID, _
.F_Name = c.F_Name, _
.M_Name = c.M_Name, _
.L_Name = c.L_Name, _
.MyID = c.MyID, _
.Site = c.Site.GetValueOrDefault, _
.bk_Building = c.bk_Building, _
.bk_City = c.bk_City, _
.bk_Zip = c.bk_Zip.GetValueOrDefault, _
.bk_Phone = c.bk_phone, _
.email = c.email, _
.DeptZone = c.DeptZone, _
.QuartID = c.QuartID.GetValueOrDefault, _
.BikerDays = c.BikerDays.GetValueOrDefault, _
.BikerMiles = c.BikerMiles.GetValueOrDefault, _
.BikerTime = c.BikerTime.GetValueOrDefault, _
.BKLockID = c.BKLockID.GetValueOrDefault, _
.bk_Start_DT = c.bk_Start_DT, _
.bk_End_DT = c.bk_End_DT, _
.bk_Quarter = c.bk_Quarter.GetValueOrDefault, _
.bk_Year = c.bk_Year.GetValueOrDefault, _
.bk_Comments = c.bk_Comments, _
.IsActive = c.IsActive.GetValueOrDefault _
}).ToList()
This works great and sorts on L_Name. But I am trying to allow the user to sort the gridview themselves. So I am passing in the SortExpression as a string. But I don't know how to incorperate the SortExpression into the LINQ Query.
I tried
Order By c. & SortExpression
But that did not work.
You should check out something called a Dynamic Query in Linq.
Using the LINQ Dynamic Query Library
Here's an article that talks about dynamic sorting with linq using a sortexpression string:
http://www.codeproject.com/KB/recipes/Generic_Sorting.aspx
Basically, you'll need to build the expression tree manually.
(this code is from the link above)
Public Function Sort(ByVal source As IEnumerable(Of T), _
ByVal sortBy As String, _
ByVal sortDirection As String) As IEnumerable(Of T)
Dim param = Expression.Parameter(GetType(T), "item")
Dim sortExpression = Expression.Lambda(Of Func(Of T, Object))_
(Expression.Convert(Expression.[Property](param, sortBy), _
GetType(Object)), param)
Select Case sortDirection.ToLower
Case "asc"
Return source.AsQueryable().OrderBy(sortExpression)
Case Else
Return source.AsQueryable().OrderByDescending(sortExpression)
End Select
End Function